React 重温之 Error Boundaries
什么是Error Boundaries
Error Boundaries(错误边界)是React 16+引入的一个新概念,那么具体是什么东西呢?
话不多说,先看官方怎么说:
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
这段文字信息量很大,需要拆成两部分来看
第一部分
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.
简单翻译过来就是:错误边界是一个组件,这个组件可以用来捕获它的子组件中产生的错误,记录错误日志并在错误发生的是,展示一个“回退”或者说是一个错误信息页面,以避免因为局部组件错误而导致的整个组件树崩溃。
第二部分
Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
简单翻译过来就是说: 错误边界可以在捕获其 其子组件的渲染、生命周期函数以及构造函数内的错误。
边界能力
既然叫错误边界,一方面,可以理解成这个组件是所有子组件发送错误的捕获者,所有子组件的错误到达错误边界组件后,错误信息被拦截并不再向上冒泡,所以这个组件就是错误的一个边界;另一方面,也可以理解成拦截错误的能力是有边界的,不是所有错误都可以捕获,那具体什么错误可以捕获什么不能捕获呢?
上面已经提到,错误边界可以拦截子组件的渲染、生命周期函数以及构造函数内的错误。简单的说就是子组件声明周期内的错误。
无法捕获的错误如下:
Event handlers 事件处理函数触发的错误
Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks) 异步代码
Server side rendering 服务端渲染
Errors thrown in the error boundary itself (rather than its children) 自己产生的错误
why ?
原则上来讲,错误边界是用来保证React可以正常渲染UI的,而不是真的用来捕获异常的。
当非生命周期函数中发生错误的时候,React依然可以保证UI渲染可以完成,只是可能会有错误提示。。。
所以,正确的做法应该是在声明周期中的错误用错误边界来处理,其它地方的错误依然使用 try。。catch。。
怎么用
还是先看官方示例:
A class component becomes an error boundary if it defines a new lifecycle method called componentDidCatch(error, info):
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
一个声明了componentDidCatch生命周期函数的类组件,自动变成一个边界组件。然后就可以像普通组件一样使用了
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
错误边界仅可以捕获其子组件的错误。错误边界无法捕获其自身的错误。如果一个错误边界无法渲染错误信息,则错误会向上冒泡至最接近的错误边界。这也类似于 JavaScript 中 catch {} 的工作机制。
one more thing
自 React 16 开始,任何未被错误边界捕获的错误将会卸载整个 React 组件树。