[React翻译]Error Boundaries(错误边界)

Error Boundaries(错误边界)

介绍

UI的某一部分抛错不该该致使整个App都崩掉,React 16由此提出一个新概念叫“error boundary”,错误边界html

“error boundary”是什么呢,是一个React组件。error boundary能捕获子组件树中发生的任何错误,而后打日志,返回fallback UI。react

error boundary能捕获哪儿的错误:git

  1. render里
  2. 生命周期方法里的
  3. 子组件树的constructor里的

error boundary不能捕获哪儿的错误:github

  1. 事件处理程序的错(learn more)
  2. 异步代码的错 (e.g. setTimeout or requestAnimationFrame callbacks)
  3. ssr的错
  4. error boundary自个儿的错

若是一个组件定义了static getDerivedStateFromError()或componentDidCatch()或两个都有,那么这个组件就是一个error boundary。npm

static getDerivedStateFromError()用于抛错后返回fallback UI,componentDidCatch()用于打错误日志浏览器

下面举个例子babel

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // 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里就能够了app

<ErrorBoundary>
  <MyWidget /> </ErrorBoundary>
复制代码

ErrorBoundary至关于组件的catch{}块。只要class型的组件能用ErrorBoundary,function型的不能用。异步

一般实践推荐在App里一处定义,到处使用ide

注意,ErrorBoundary只catch它子组件的错,它自个儿的错不catch。固然了,若是ErrorBoundary抛错了那它会传到它上面的ErrorBoundary去处理。

例子

Check out this example of declaring and using an error boundary with React 16.

Error Boundaries放哪好呢?

随便,看你怎么写。包裹整个APP也成,包裹一个小组件也成

未捕获错误的新行为

这个变化意义重大。对于React 16来讲,未被Error Boundaries捕获的错误会 unmount 整个react组件树

为啥这么作呢?React的人认为,宁肯我给整个APP都挂掉也比返一个部分挂掉的UI强。比方说通讯类app,一个挂掉的UI可能致使信息发错人;再比方说支付类APP,显示错误的帐户余额还不如啥都不显示

多用Error Boundaries更带来更好的用户体验。Facebook Messenger 给sidebar,info panel,conversation log都各自包了一层ErrorBoundary,这样某个组件挂了不会影响其余的,并且能展现不一样的fallback UI

推荐你用一些JS错误汇报工具

组件堆栈跟踪

Error caught by Error Boundary component

Create React App默认配置的,若是没用要加 this plugin到babel。

开发环境使用,生产环境禁用!

组件堆栈跟踪的组件名是调Function.name 获得的,低版本浏览器本身polyfill

How About try/catch?

try/catch只适用于当即执行的代码

try {
  showButton();
} catch (error) {
  // ...
}
复制代码

可是react组件是声明式的,说明将要渲染什么,Error boundaries保留了react声明式的特色

blabalbla...

关于Event Handlers

Error boundaries do not catch errors inside event handlers!

渲染的时候不会处理事件的,因此事件处理程序抛错react会知道的。

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

  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>
  }
}
复制代码

关于React 15的名称变化

unstable_handleError 改为了 componentDidCatch

这部分变化codemod能够帮你自动迁移代码

相关文章
相关标签/搜索