介绍
错误界限在React v16中被引入,作为捕捉在渲染阶段发生的棘手错误的一种方式,在过去,这会导致应用程序完全卸载,用户只会看到一个空白的网页,这不是理想的!
在本文中,您将通过代码片段和交互式演示文稿了解 Error Boundaries。
前提条件
要跟随这篇文章,你将需要:
您可以阅读我们的 如何在 React.js 中编码系列。
本教程已通过 Node v16.4.2, npm
v7.19.1 和 react
v17.0.2 进行验证。
遇到错误没有错误界限
在开发过程中,我们不可避免地会遇到我们的应用程序中意外的错误,您可能会试图访问一个不存在的对象上的深陷属性,或者有时它无法控制(例如对第三方 API 的 HTTP 请求失败)。
在下面的演示文稿中,我们将模拟错误,以查看没有错误界限的情况。
1[label BuggyCounter.js]
2import React from 'react';
3
4class BuggyCounter extends React.Component {
5 state = {
6 counter: 0,
7 };
8
9 handleClick = () => {
10 this.setState({
11 counter: this.state.counter + 1,
12 });
13 };
14
15 render() {
16 if (this.state.counter === 5) {
17 // Simulate an error!
18 throw new Error('Simulated error.');
19 }
20 return (
21 <div>
22 <h1>{this.state.counter}</h1>
23 <button onClick={this.handleClick}>+</button>
24 </div>
25 );
26 }
27}
28
29export default BuggyCounter;
请访问 CodePen 上的实时代码示例 alligatorio-react-error-boundaries-1
通过 @wle8300 。
点击 +(增量)按钮,观察它如何在5失败。
1[secondary_label Output]
2Uncaught Error: Simulated error.
当应用程序遇到错误时,组件会完全拆卸,用户将留下一个空白的HTML页面,这可能会让用户感到困惑,他们不知道下一步该怎么做。
错误界限提供了一种方法来优雅地处理这些错误!
遇到错误与错误边界
错误界限是什么? 与你想象的不同,它不是一个新的组件或JavaScript库,它更像是处理React组件中的错误的策略。
具体来说,它是使用 React 组件中可用的两种方法:
1[label MyErrorBoundaryExample.js]
2import React from 'react';
3
4class MyErrorBoundaryExample extends React.Component {
5 state = {
6 error: null,
7 };
8
9 static getDerivedStateFromError(error) {
10 // Update state so next render shows fallback UI.
11 return { error: error };
12 }
13
14 componentDidCatch(error, info) {
15 // Log the error to an error reporting service
16 logErrorToExampleService(error, info);
17 }
18
19 render() {
20 if (this.state.error) {
21 // You can render any custom fallback UI
22 return <p>Something broke</p>;
23 }
24 return this.props.children;
25 }
26}
27
28export default MyErrorBoundaryExample;
static getDerivedStateFromError
是一种生命周期方法,允许错误边界有机会更新state
,从而触发最后一个render()
. 在上面的代码片段中,该状态被用来揭示人类友好的错误消息,而不是破坏的组件(例如,this.props.children
)。componentDidCatch
是一种生命周期方法,旨在触发副作用(例如,将错误登录到诸如 Crashlytics等工具)。
任何 React 组件被视为错误界限,当它使用至少其中一种生命周期方法时。
良好的做法表明,您将希望创建一个专门构建为错误边界的组件,而不是将错误处理逻辑混合到一般组件中。
让我们稍微修改MyErrorBoundary
,然后围绕<BuggyComponent>
包装,以便捕捉到错误!
1[label MyErrorBoundary.js]
2import React from 'react';
3
4class MyErrorBoundary extends React.Component {
5 state = {
6 errorMessage: '',
7 };
8
9 static getDerivedStateFromError(error) {
10 return { errorMessage: error.toString() };
11 }
12
13 componentDidCatch(error, info) {
14 this.logErrorToServices(error.toString(), info.componentStack);
15 }
16
17 // A fake logging service.
18 logErrorToServices = console.log;
19
20 render() {
21 if (this.state.errorMessage) {
22 return <p>{this.state.errorMessage}</p>;
23 }
24 return this.props.children;
25 }
26}
27
28export default MyErrorBoundary;
和App.js
:
1[label App.js]
2import React from 'react';
3import BuggyCounter from './BuggyCounter';
4import MyErrorBoudnary from './MyErrorBoundary';
5
6class App extends React.Component {
7 refreshPage = () => {
8 history.go(0);
9 };
10
11 render() {
12 return (
13 <div>
14 <MyErrorBoundary>
15 <BuggyCounter />
16 </MyErrorBoundary>
17 <hr />
18 <button onClick={this.refreshPage}>Refresh Page</button>
19 </div>
20 );
21 }
22}
23
24export default App;
BuggyCounter.js
仍然是一样的。
请访问 CodePen 上的实时代码示例 alligatorio-react-error-boundaries-2
通过 @wle8300 。
尝试再次点击 +(增量)按钮.一旦达到5,它会顺利崩溃。此外,您可以打开您的控制台,查看堆栈跟踪!
而不是完全崩溃,我们可以使用错误界限来代替倒退的用户界面,这为用户提供视觉反馈,让他们能够继续与我们的应用程序互动。
他们可以选择远离,甚至联系客户服务,以帮助解决他们的情况! 这是一个很好的方式来赎回不幸的用户体验。
错误界限和尝试捕捉
的比较
错误界限实际上并不与试...捕
陈述直接竞争,错误界限仅用于拦截来自 React 组件的 3 个位置的错误:
- 在
render
阶段 - 在生命周期方法
- 在
constructor
基本上...一个组件的 React-y 部分。
作为对比点,以下是错误边界无法捕捉错误的地方:
- 事件处理器(例如,
onClick
,onChange
,等等) setTimeout
或requestAnimationFramecallbacks
- 服务器侧渲染(SSR)
- 以及由错误界限本身引起的错误(而不是其子女)
因此,错误界限并不真正影响您如何使用试用...捕获
,它们都需要作为React中处理错误的强大策略。
结论
在本文中,您了解了错误界限。
<$>[注] **注:**错误界限仅在基于类的 React 组件中可用。
现在,自 React 版本 16 以来, Error Boundaries 已经可用,通常建议您在应用程序根部使用至少一个 Error Boundary (例如,App.js 文件)。
未来,您可以使用几种不同类型的错误界限,这些错误界限使用不同的落后用户界面,或者只会向第三方服务记录错误。
查看 官方 React 文件 获取更多信息!