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

本文围绕React 16的错误边界(Error Boundaries)展开。它是能捕获子组件树错误、打日志并返回fallback UI的React组件,介绍了其能与不能捕获错误的场景、使用示例、放置位置,还提及未捕获错误的新行为、组件堆栈跟踪等内容,强调多用它可提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Error Boundaries(错误边界)

介绍

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

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

error boundary能捕获哪儿的错误:

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

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

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

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

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

下面举个例子

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里就可以了

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

ErrorBoundary相当于组件的catch{}块。只要class型的组件能用ErrorBoundary,function型的不能用。

通常实践推荐在App里一处定义,处处使用

注意,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错误汇报工具

组件堆栈跟踪

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可以帮你自动迁移代码

转载于:https://juejin.im/post/5c925b2e5188252d6f431752

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值