📜  反应错误边界

📅  最后修改于: 2020-12-19 03:41:04             🧑  作者: Mango

反应错误边界

过去,如果我们在组件内部遇到任何JavaScript错误,它将破坏React的内部状态并将React置于下一个渲染状态。在React组件中没有办法处理这些错误,也没有提供任何从它们中恢复的方法。但是, React 16引入了一个新概念,即通过使用错误边界来处理错误。现在,如果在用户界面的一部分中发现任何JavaScript错误,则不会破坏整个应用程序。

错误边界是React组件,可在我们应用程序中的任何位置捕获JavaScript错误,记录这些错误并显示后备UI。它不会破坏整个应用程序组件树,仅在组件发生错误时才呈现后备UI。错误边界会在组件生命周期方法及其下的整个树的构造函数的渲染过程中捕获错误。

对于简单的React应用程序,我们可以一次声明一个错误边界,并将其用于整个应用程序。对于具有多个组件的复杂应用程序,我们可以声明多个错误边界以恢复整个应用程序的每个部分。

我们还可以将错误报告给诸如Rollbar的错误监视服务。此监视服务提供了跟踪有多少用户受到错误影响,查找错误原因并改善用户体验的功能。

类中的错误边界

如果类组件定义了新的生命周期方法(静态getDerivedStateFromError()或componentDidCatch(error,info)),则可能成为错误边界。当引发错误时,我们可以使用静态getDerivedStateFromError()来呈现后备UI,并且可以使用componentDidCatch()来记录错误信息。

错误边界无法捕获自身内部的错误。如果错误边界未能呈现错误消息,则错误将转到其上方最近的错误边界。它类似于JavaScript中的catch {}块。

如何实现错误边界

步骤1创建一个扩展React组件并在其中传递props的类。

步骤2现在,添加componentDidCatch()方法,该方法使您可以在树中它们下方的组件中捕获错误。

步骤3接下来,添加render()方法,该方法负责如何呈现组件。例如,它将显示错误消息,例如“出问题了”。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  static getDerivedStateFromError(error) {
    // It will update the state so the next render shows the fallback UI.
    return { hasError: true };
  }
  componentDidCatch(error, info) {
    // It will catch error in any component below. We can also log the error to an error reporting service.
    logErrorToMyService(error, info);
  }
  render() {
    if (this.state.hasError) {
        return (
          
Something is wrong.
; ); } return this.props.children; } }

步骤4现在,我们可以将其用作常规组件。在HTML中添加要包含在错误边界中的新组件。在此示例中,我们在MyWidgetCounter组件周围添加了错误边界。


       

在哪里放置错误边界

错误边界完全取决于您。您可以在应用程序组件的顶层使用错误边界,也可以将其包装在各个组件上,以防止它们破坏应用程序的其他部分。

让我们来看一个例子。

import React from 'react';
import './App.css'

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: false, errorInfo: null };
  }
  
  componentDidCatch(error, errorInfo) {
    // Catch errors in any components below and re-render with error message
    this.setState({
      error: error,
      errorInfo: errorInfo
    })
  }
  
  render() {
    if (this.state.errorInfo) {
      return (
        

Something went wrong.

{this.state.error && this.state.error.toString()}
{this.state.errorInfo.componentStack}
); } return this.props.children; } } class BuggyCounter extends React.Component { constructor(props) { super(props); this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(({counter}) => ({ counter: counter + 1 })); } render() { if (this.state.counter === 3) { throw new Error('I crashed!'); } return

{this.state.counter}

; } } function App() { return (

Example of Error Boundaries


These two counters are inside the same error boundary.


These two counters are inside of their individual error boundary.

); } export default App

在上面的代码片段中,当我们单击数字时,它会增加计数器。计数器被编程为在达到3时抛出错误。它模拟组件中的JavaScript错误。在这里,我们以两种方式使用错误边界,如下所示。

首先,这两个计数器在同一错误边界内。如果有人崩溃,则错误边界将替换它们两者。


          
          

其次,这两个计数器在其各自的错误边界之内。因此,如果任何人崩溃,其他人都不会受到影响。



输出:

当我们执行上面的代码时,我们将得到以下输出。

当计数器达到3时,将提供以下输出。

未捕获错误的新行为

这是与错误边界相关的重要含义。如果错误没有被任何错误边界捕获,将导致整个React应用程序的卸载。

事件处理程序中的错误边界

错误边界不允许在事件处理程序中捕获错误。 React不需要任何错误边界即可从事件处理程序中的错误中恢复。如果需要在事件处理程序中捕获错误,则可以使用JavaScript try-catch语句。

在下面的示例中,您可以看到事件处理程序将如何处理错误。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    try {
      // Do something which can throw error
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      return 
          

It caught an error.

} return
Click Me
} }