React 错误边界(Error Boundaries)

更新日期: 2021-12-17阅读: 1.3k标签: 错误

前言

react 项目中,很常见遇到页面由于某个 React 组件渲染错误(代码书写错误不规范或后端接口字段调整出错),导致整个应用被挂载出现白屏,且可能无法追踪造成影响极大,究其原因觉得是React 设计的坑点 自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载。 针对此类问题,我们如何来进行感知上报以及应急兜底呢?

Error Boundaries 是 React16 提出来用来捕获渲染时错误的概念,Error Boundaries 是一种 React 组件,这种组件可以捕获并打印发生在其子组件树任何位置的 JavaScript 错误,且会渲染出兜底 UI

Error Boundaries

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

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

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return { hasError: true };
  }

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

  render() {
    if (this.state.hasError) {
      // 自定义降级后的 UI 并渲染
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}
  • static getDerivedStateFromError:在出错后有机会修改 state 触发最后一次错误 fallback 的渲染。
  • componentDidCatch:用于出错时副作用代码,比如错误上报等。

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

错误边界的工作方式类似于 JavaScript 的 catch {},不同的地方在于错误边界只针对 React 组件。只有 class 组件才可以成为错误边界组件。

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

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

注意: 错误边界仅可以捕获其子组件的错误,无法捕获其自身的错误。如果一个错误边界无法渲染错误信息,则错误会冒泡至最近的上层错误边界,这也类似于 JavaScript 中 catch {} 的工作机制。

React 16 定义和使用错误边界的例子

Error Boundaries 无法捕获错误

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

  • 回调事件,由于回调事件执行时机不在渲染周期内,因此无法被 Error Boundaries Catch 住,如有必要得自行 try/catch

  • 异步代码,比如 setTimeout 或 requestAnimationFrame,和第一条同理

  • 服务端渲染

  • Error Boundaries 组件自身触发的错误,只能捕获其子组件的错误

这也是使用 Error Boundaries 最容易有疑问的地方。

对于不能捕获到的错误情况, 是因为 getDerivedStateFromError 执行在 render 阶段,componentDidCatch 执行在 commit 阶段,过了这两个阶段(即一次渲染周期)就无法捕获到。


无法捕获编译时错误

React 官方 API Error Boundaries 也只能捕获运行时错误,而对编译时错误无能为力。

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

Error Boundaries 可作用于 Function Component

虽然函数式组件无法定义 Error Boundaries,但 Error Boundaries 可以捕获函数式组件的异常错误:

// ErrorBoundary 组件
class ErrorBoundary extends React.Component {
  // ...
}

// Hooks 函数组件
const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, [props.a.b]);

  return <div />;
};

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

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

const Child = (props) => {
  React.useEffect(() => {
    console.log(1);
    props.a.b;
    console.log(2);
  }, []);

  return <div />;
};

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

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

总结

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

Error Boundaries 也不是万能的,更多时候我们要避免并及时修复错误以及错误兜底降低影响,并在第一时间内监控起来并快速修复

来自:https://github.com/pfan123/Articles/issues/79

链接: https://www.fly63.com/article/detial/11198

解决Cannot read property range of null 错误

vue工程npm run serve/start/dev启动时,node_modules文件报:Cannot read property range of null 错误,该问题是babel-eslint版本更新问题导致的;

HTTP 400 错误 - 请求无效 (Bad request)

在ajax请求后台数据时有时会报 HTTP 400 错误 - 请求无效 (Bad request);出现这个请求无效报错说明请求没有进入到后台服务里;原因:前端提交数据的字段名称或者是字段类型和后台的实体类不一致

js异步错误捕获

我们都知道 try catch 无法捕获 setTimeout 异步任务中的错误,那其中的原因是什么。以及异步代码在 js 中是特别常见的,我们该怎么做才比较?

不能执行已释放Script的代码

父页面初始化声明变量a为数组(数组对象是引用类型,赋值传递的是地址),创建iframe子页面后给父页面变量a赋值,赋值后销毁iframe子页面,再次调用变量a的时候就会抛出异常‘SCRIPT5011:不能执行已释放Script的代码’。

JS错误处理:前端JS/Vue/React/Iframe/跨域/Node

js错误的实质,也是发出一个事件,处理他,error实例对象message:错误提示信息,name:错误名称(非标准属性)宿主环境赋予

nodejs提示 cross-device link not permitted, rename 错误解决方法

文件上传的功能时候,调用fs.renameSync方法错误,这个提示是跨区重命名文件出现的权限问题。先从源文件拷贝到另外分区的目标文件,然后再unlink,就可以了。

Js中使用innerHTML的缺点是什么?

如果在JavaScript中使用innerHTML,缺点是:内容随处可见;不能像“追加到innerHTML”一样使用;innerHTML不提供验证,因此我们可能会在文档中插入有效的和破坏性的HTML并将其中断

Web前端开发,必须规避的8个错误点!

现在,有越来越多所谓的“教程”来帮助我们提高网站的易用性。我们收集了一些在Web开发中容易出错和被忽略的小问题,并且提供了参考的解决方案,以便于帮助Web开发者更好的完善网站。

web前端错误监控

为什么要做前端错误监控?1. 为了保证产品的质量2. 有些问题只存在于线上特定的环境3. 后端错误有监控,前端错误没有监控,前端错误分为两类: 即时运行错误和资源加载错误

自定义错误及扩展错误

当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 HttpError,对于数据库操作错误,我们需要 DbError,对于搜索操作错误,我们需要 NotFoundError,等等

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!