前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >148. 精读《React Error Boundaries》

148. 精读《React Error Boundaries》

作者头像
黄子毅
发布2022-03-14 17:37:15
4360
发布2022-03-14 17:37:15
举报
文章被收录于专栏:前端精读评论

1 引言

Error Boundaries 是 React16 提出来用来捕获渲染时错误的概念,今天我们一起读一读 A Simple Guide to Error Boundaries in React 这篇文章,了解一下这个重要机制。

2 概述

Error Boundaries 可以用来捕获渲染时错误,API 如下:

代码语言:javascript
复制
class MyErrorBoundary extends Component {
  state = {
    error: null,
  };

  static getDerivedStateFromError(error) {
    // 更新 state,下次渲染可以展示错误相关的 UI
    return { error: error };
  }

  componentDidCatch(error, info) {
    // 错误上报
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.error) {
      // 渲染出错时的 UI
      return <p>Something broke</p>;
    }
    return this.props.children;
  }
}
  • static getDerivedStateFromError: 在出错后有机会修改 state 触发最后一次错误 fallback 的渲染。
  • componentDidCatch: 用于出错时副作用代码,比如错误上报等。

这两种方法中任意一个被定义时,这个组件就会成为 Error Boundary 组件,可以阻止子组件渲染时报错。

最后作者还提出一个建议,建议将 Error Boundary 单独作为一个组件,而不是将错误监听方法与业务组件耦合,一方面考虑到复用,另一方面则因为错误检测只对子组件生效。

好吧,其实 React 官方文档比这篇文章介绍的详细的多得多,原文介绍到此结束。

3 精读

React Error Boundaries 官方文档 里提到了四种无法 Catch 的错误场景:

  1. 回调事件。由于回调事件执行时机不在渲染周期内,因此无法被 Error Boundary Catch 住,如有必要得自行 try/catch。
  2. 异步。比如 setTimeoutrequestAnimationFrame,和第一条同理。
  3. 服务端渲染。
  4. Error Boundary 组件自身触发的错误。因为只能捕获其子组件的错误。

这也是使用 Error Boundaries 最容易有疑问的地方。除了上面的情况,笔者结合自身经验再列举几种异常边界场景。

无法捕获编译时错误

很明显,即便是 React 官方 API Error Boundary 也只能捕获运行时错误,而对编译时错误无能为力。

编译时错误包括不限于编译环境错误、运行前的框架错误检查提示、TS/Flow 类型错误等,这些都是 Error Boundary 无法捕获的,而且没有更好的办法 Catch 住,遇到编译错误就在编译时解决吧,仅关注运行时错误就好了。

可以作用于 Function Component

虽然函数式组件无法定义 Error Boundary,但 Error Boundary 可以捕获函数式组件的错误,因此可以曲线救国:

代码语言:javascript
复制
// ErrorBoundary 组件
class ErrorBoundary extends React.Component {
  // ...
}

// 可以捕获所有组件异常,包括 Function Component 的子组件
const App = () => {
  return (
    <ErrorBoundary>
      <Child />
    </ErrorBoundary>
  );
};

对 Hooks 也可生效

对于 Hooks 中异常也可以生效,比如下面的代码:

代码语言:javascript
复制
const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, [props.a.b]);

  return <div />;
};

要注意的是,出现在 deps 中的错误会立即被 Catch,导致 console.log(1) 都无法打印。但如果是下面的代码,则可以打印出 console.log(1),无法打印出 console.log(2):

代码语言:javascript
复制
const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, []);

  return <div />;
};

所以 React 官网的这句话并不是指 Error Boundary 对 Hooks 不生效,而是指 Error Boundary 无法以 Hooks 方式指定,对功能是没有影响的:

componentDidCatch and getDerivedStateFromError: There are no Hook equivalents for these methods yet, but they will be added soon.

所以这里的理解要注意一下,另外 React 官方文档 Hooks FQA 有很多宝藏,建议抽时间逐条阅读。

4 总结

Error Boundary 可以捕获所有子元素渲染时异常,包括 render、各生命周期函数,但也有很多使用限制,希望你可以正确使用它。

错误捕获也不是万能的,更多时候我们要避免并及时修复错误,通过错误捕获降低出错时对用户体验的影响,并在第一时间内监控起来并快速修复。

最后,你有明明正确使用了 Error Boundary 却依然无法 Catch 住的错误 Case 吗?

讨论地址是:精读《React Error Boundaries》 · Issue #246 · dt-fe/weekly

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端精读评论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 引言
  • 2 概述
  • 3 精读
    • 无法捕获编译时错误
      • 可以作用于 Function Component
        • 对 Hooks 也可生效
        • 4 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档