如何在 React 中使用错误边界

介绍

错误界限在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,等等)
  • setTimeoutrequestAnimationFramecallbacks
  • 服务器侧渲染(SSR)
  • 以及由错误界限本身引起的错误(而不是其子女)

因此,错误界限并不真正影响您如何使用试用...捕获,它们都需要作为React中处理错误的强大策略。

结论

在本文中,您了解了错误界限。

<$>[注] **注:**错误界限仅在基于类的 React 组件中可用。

现在,自 React 版本 16 以来, Error Boundaries 已经可用,通常建议您在应用程序根部使用至少一个 Error Boundary (例如,App.js 文件)。

未来,您可以使用几种不同类型的错误界限,这些错误界限使用不同的落后用户界面,或者只会向第三方服务记录错误。

查看 官方 React 文件 获取更多信息!

Published At
Categories with 技术
Tagged with
comments powered by Disqus