分享个人 Full-Stack JavaScript 项目开发经验
React 组件内未被捕获的 JavaScript 错误会导致 React 卸载整个 React 组件树。在 React 16 引入了错误边界用于捕获渲染期间、生命周期方法内、以及整个组件树构造函数内的错误。
本文的应用例子是基于使用 react-redux 和 react-router-dom 的 React 应用程序。如果你还未了解它们的使用,可以先参阅以下两篇文章:
我们先创建一个通用的错误边界组件:
import React from "react";
export class ErrorBoundary extends React.Component {
state = {hasError: false};
componentDidCatch(error, info) {
this.setState({hasError: true});
}
render() {
if (this.state.hasError) {
return (
<p className="bg-danger error-boundary-tips">{this.props.name}发生了未知错误!</p>
);
}
return this.props.children;
}
}
该组件的特别之处在于它定义了 componentDidCatch 的生命周期方法。当它的子组件在渲染期间、生命周期方法或构造函数中出现错误时,将会被捕获并且调用该方法。这时候我们设置一个 state 用于告诉错误边界组件渲染特定的错误提示。如果没有错误发生,则渲染正常的子组件。
在 React Router 的 Route 组件中,常见的做法是将 react-redux 的容器组件作为路径匹配时渲染的组件,如:
// ......
<Route exact path="/clear" component={ClearContainer}/>
// ......
而该容器组件会连接一个具体的 UI 组件:
import {connect} from "react-redux";
import {ClearUI} from "../components/clear/clear";
export const ClearContainer = connect(
state => ({
// ......
}), dispatch => ({
// ......
})
)(ClearUI);
要捕获该 UI 组件内的错误,我们需要为它包裹一层错误边界,在错误发生时渲染错误提示 UI(其它路由组件仍然可以正常工作):
import React from "react";
import PropTypes from "prop-types";
import {ErrorBoundary} from "../errorBoundary";
class Clear extends React.Component {
// ......
}
Clear.propTypes = {
// ......
};
export const ClearUI = (props) =>
<ErrorBoundary name="清理冗余组件">
<Clear {...props}/>
</ErrorBoundary>
上面的 ClearUI 组件包裹了一层错误边界,并且把 props 属性传递给原来的 Clear 组件。