错误处理
React 16 之前,组件在运行期间如果执行出错,就会阻塞整个应用的渲染,这时候只能刷新页面才能恢复应用。React 16 引入了新的错误处理机制,默认情况下,当组件中抛出错误时,这个组件会从组件树中卸载,从而避免整个应用的崩溃。这种方式比起之前的处理方式有所进步,但用户体验依然不够友好。React 16 还提供了一种更加友好的错误处理方式——错误边界(Error Boundaries)。错误边界是能够捕获子组件的错误并对其做优雅处理的组件。优雅的处理可以是输出错误日志、显示出错提示等,显然这比直接卸载组件要更加友好。
定义了 componentDidCatch(error, info) 这个方法的组件将成为一个错误边界,现在我们创建一个组件 ErrorBoundary:
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(err, info) {
// 显示错误UI
this.setState({ hasError: true });
// 同时输出错误日志
console.log(err, info);
}
render() {
if (this.state.hasError) {
return <h1>Oops, something went wrong!</h1>;
}
return this.props.children;
}
}
然后在 App 中使用 ErrorBoundary:
class App extends Component {
constructor(props) {
super(props);
this.state = {
user: { name: "react" }
};
}
// 将user置为null,模拟异常
onClick = () => {
this.setState({ user: null });
};
render() {
return (
<div>
<ErrorBoundary>
<Profile user={this.state.user} />
</ErrorBoundary>
<button onClick={this.onClick}>更新</button>
</div>
);
}
}
const Profile = ({user}) => <div>name: {user.name}</div>;
点击更新按钮后,Profile 接收到的属性 user 为 null,程序会抛出 TypeError,这个错误会被 ErrorBoundary 捕获,并在界面上显示出错提示。注意,使用 create-react-app 创建的项目,当程序发生错误时,create-react-app 会在页面上创建一个浮层显示错误信息,要观察 ErrorBoundary 的正确效果,需要先关闭错误浮层。
本节项目源代码的目录为 /chapter-03/react16-error-boundary 。