React 16.0中的新特性——Error Boundaries及其注意点

简要介绍:在之前的React版本中规定,如果在组件中javascript报错,那么会在下一次的render中阻断,并且现实空白页。React之前没有提供一种合适的处理组件错误的方法,而React16.0中通过Error Boundaries来处理组件内部的错误,从而可以修正错误组件。

1.什么是Error Boundaries?

单一组件内部错误,不应该导致整个应用报错并显示空白页,而Error Boundaries解决的就是这个问题。

(1)Error Boundaries的实现

如何使组件变成一个“Error Boundaries”,只需要在组件中定义个新的生命周期函数——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;
  }
}

上述的ErrorBoundary就是一个“错误边界”,然后我们可以这样来使用它:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

Erro Boundaries本质上也是一个组件,通过增加了新的生命周期函数componentDidCatch使其变成了一个新的组件,这个特殊组件可以捕获其子组件树中的js错误信息,输出错误信息或者在报错条件下,显示默认错误页。

注意一个Error Boundaries只能捕获其子组件中的js错误,而不能捕获其组件本身的错误和非子组件中的js错误。

(2)componentDidCatch()生命周期函数

componentDidCatch是一个新的生命周期函数,当组件有了这个生命周期函数,就成为了一个Error Boundaries。下面我们来看componnetDidCatch()中的参数:

componentDidCatch(error, info) {


}

error参数,表示的是被抛出的错误的信息,而info是一个对象包含了组件堆栈中的信息(也就是在发生错误的子组件中层层传递错误信息,到顶层的Error Boundaries,每一层中的组件名)。

(3)Component Stack Traces

下面我们来看组件堆栈轨迹,我们假设这样一个结构:

<App>
  <div>
      <ErrorBoundary>
        <Child></Child>
      </ErrorBoundary>
  </div>
</App>

如果在Child组件中发生了js错误,那么堆栈的报错信息应该如下:

the error is located at :
     in Child  (created by App)
     in ErrorBoundary(created by App)
     in div (created by App)
     in App

如果需要报错信息显示错误组件所在的具体的行数和位置,可以使用babel-plugin-transform-react-jsx-source插件。

(4)try/catch模块

我们使用了Error Boundaries来抛出组件的内部异常,那么什么时候可以使用try / catch模块呢。我们知道Error Boundaries仅仅抛出了子组件的错误信息,并且不能抛出组件中的事件处理函数中的异常。(因为Error Boundaries仅仅能保证正确的render,而事件处理函数并不会发生在render过程中),我们需要用try/catch来处理事件处理函数中的异常,举例来说:

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

  handleClick = () => {
    try {
      // Do something that could throw
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      return <h1>Caught an error.</h1>
    }
    return <div onClick={this.handleClick}>Click Me</div>
  }
}

上述的代码中,我们在 MyComponent组件的handleClick 通过try/catch的方式来抛出异常,与一般javascript的异常处理方式相同。

2.注意事项

下面我们来看哪些情况下不能通过Error Boundaries来实现catch{}错误

(1)组件的内部的事件处理函数,因为Error Boundaries处理的仅仅是Render中的错误,而Hander Event并不发生在Render过程中。

(2)异步函数中的异常,Error Boundaries不能catch,比如setTimeout或者setInterval ,requestAnimationFrame等函数中的异常。

(3)服务器端的rendering

(4)发生在Error Boundaries组件本身的错误

猜你喜欢

转载自blog.csdn.net/liwusen/article/details/78521006
今日推荐