过去,组件内部的 JavaScript 错误经常会破坏 React 的内部状态,并导致它在下一次渲染时发生奇奇怪怪的错误。这些错误通常总是由应用程序代码中的早期错误引起,但在之前版本的 React 没有提供在组件中优雅地处理它们的方法。
针对“部分 UI 的错误不应当导致整个应用的崩溃” 这个理念,React16 引入了一个新的概念 “Error Boundaries( 错误边界)”。Error Boundaries
是一个特殊的 React 组件, 它用来捕获发生在子组件树的 js 错误,并输出这些错误,显示一个回调的 UI,避免一个组件的一个错误导致整个组件树的崩溃。
在学习它之前,我们先要了解一下它的不适用场景:
哪些地方可以使用 Error Boundaries
首先我们要知道,它目前不能捕获这些类型的错误:
- 事件处理器(Event handlers)
- 异步代码中的错误,比如
setTimeout
或requestAnimationFrame
。 - 服务端渲染(Server side rendering)。
- 它自身代码抛出的异常。
它可以用来处理的错误:
它可以捕获发生在组件的 render
方法和生命周期方法,以及其子孙组件的 render
方法和生命周期方法所抛出的错误。
使用
它也是一个 React 组件,使用方法与其他组件差别不大,区别在于,它需要定义一个新的生命周期方法 componentDidCatch(error, info)
:
class ErrorBoundary extends React.Component { |
需要注意的是,在 React16 中,如果有组件发生应该被 Error Boundaries
捕获的错误,而未被任何的 Error Boundaries
所捕获,将会导致整个 React 组件树的卸载。React 官方文档是这样说明其理念的:
We debated this decision, but in our experience it is worse to leave corrupted UI in place than to completely remove it. For example, in a product like Messenger leaving the broken UI visible could lead to somebody sending a message to the wrong person. Similarly, it is worse for a payments app to display a wrong amount than to render nothing.
我们讨论了这个决定,根据我们的经验,将发生错误的 UI 留在原地比完全删除它会更糟糕。例如,在像 Messenger 这样的产品中,遗留的发生错误 UI 可能会导致某人向错误的人发送消息。同样,支付 App 显示错误的金额比不提供任何内容的结果更糟糕。
为什么不处理Event Handlers 内的错误
与 render 方法和生命周期方法不同,事件处理程序在组件渲染期间不会执行。因此,即使这类错误发生,React 仍然知道应该在屏幕上显示什么,这类错误不需要 Error Boundaries
来处理,使用 try/ catch
处理即可。