在已经发布的React 16 第一个beta版和即将发布的React 16中,添加了一个新的特性,用来处理React组件内的异常。
这个新特性是React提出的一个新的概念,叫“异常边界(Error Boundary)”。
如果你有兴趣,可以在React 16的beta版中体验一下。
阅读全文约4分钟。
本文同步发布与知乎专栏:前端微志。
什么是异常边界
在React 15和更早的版本中,组件内的JavaScript异常会污染React组件内的state,并且会在render时发出不明所以的异常。这些异常一般是由于系统运行过程中更多出现的异常,但是React没有提供一个组件内优雅地解决它们的方法,也不能恢复这些异常。
在开发者看来,用React做的一个大型系统上,UI页面上一个JavaScript代码的小小的异常,不应该影响整个系统的运行,这本来是浏览器在渲染JavaScript时默认采用的一种解析方式,但一般用React来做一个单页面应用(SPA)会把很多页面的代码打包到一起,如果一个JavaScript的报错导致整个系统不能运行,也是一件很糟糕的事情。
所以,这也算是React的设计上的一个小的缺陷,React为了帮助开发者解决这个问题,在React 16这一版中,将引入一个新概念“异常边界”,使用异常边界的组件就是异常边界组件。
异常边界是一个用来捕获组件的子组件树内的JavaScript异常,将这些异常记录下来,并显示一个回调的UI来替换掉崩溃的组件树。
异常边界组件会在组件render过程中,生命周期函数内和组件下的整个树形组件的构造函数内运行。
怎么使用异常边界
为了实现异常边界,React为组件提供了一个新的生命周期函数:
componentDidCatch(error, info)
。
请看下面的栗子,我们来包装一个异常边界组件:
class ErrorBoundary extends React.Compoent {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// 显示回调UI
this.setState({ hasError: true });
// 你也可以将异常记录到一个异常报警服务上
logErrorToMyServer(error, info);
}
render() {
if (this.state.hasError) {
// 你可以render任何自定义的回调UI
return <h1>Something went wrong.h1>;
}
return this.props.children;
}
}
然后,你就可以将异常边界组件当做一个公用组件使用,如用它来包裹其他子组件,用于捕获子组件内的JavaScript异常。举个🌰:
<MyWidget />
ErrorBoundary>
异常边界的特性
通过上面的例子,你可能会觉得,
componentDidCatch()
特别像JavaScript中的
catch()
方法块,只不过后者是用于JavaScript语句中的异常捕获,前者是用于React组件UI渲染过程中的异常捕获。
在使用异常边界时,需要注意几点: