React工作流程及Error Boundaries实现过程讲解

目录
  • 什么是Error Boundaries
  • 步骤1:捕获错误
  • 步骤2:构造callback
  • 执行callback
  • 总结

这里简单讲解下React工作流程,后文有用。分为三步:

触发更新

  • render阶段:计算更新会造成的副作用
  • commit阶段:在宿主环境执行副作用

副作用有很多,比如:

  • 插入DOM节点
  • 执行useEffect回调

好了,让我们进入主题。

什么是Error Boundaries

React提供了两个与错误处理相关的API:

  • getDerivedStateFromError:静态方法,当错误发生后提供一个机会渲染fallback
  • UIcomponentDidCatch:组件实例方法,当错误发生后提供一个机会记录错误信息

使用了这两个API的ClassComponent通常被称为Error Boundaries(错误边界)。

在Error Boundaries的子孙组件中发生的所有React工作流程内的错误都会被Error Boundaries捕获。

通过开篇的介绍可以知道,React工作流程指:

render阶段

commit阶段

考虑如下代码:

class ErrorBoundary extends Component {
  componentDidCatch(e) {
    console.warn(“发生错误”, e);
  }
  render() {
    return <div>{this.props.children}</div>;
  }
}
const App = () => (
    <ErrorBoundary>
    <A><B/></A>
    <C/>
    <ErrorBoundary>
)

A、B、C作为ErrorBoundary的子孙组件,当发生React工作流程内的错误,都会被ErrorBoundary中的componentDidCatch方法捕获。

步骤1:捕获错误

首先来看工作流程中的错误都是何时被捕获的。

render阶段的核心代码如下,发生的错误会被handleError处理:

do {
  try {
    // 对于并发更新则是workLoopConcurrent
workLoopSync();
    break;
  } catch (thrownValue) {
    handleError(root, thrownValue);
  }
} while (true);

commit阶段包含很多工作,比如:

  • componentDidMount/Update执行
  • 绑定/解绑ref
  • useEffect/useLayoutEffect callback与destroy执行

这些工作会以如下形式执行,发生的错误被captureCommitPhaseError处理:

try {
// …执行某项工作
} catch (error) {
  captureCommitPhaseError(fiber, fiber.return, error);
}

步骤2:构造callback

可以发现,即使没有Error Boundaries,工作流程中的错误已经被React捕获了。而正确的逻辑应该是:

  • 如果存在Error Boundaries,执行对应API
  • 抛出React的提示信息
  • 如果不存在Error Boundaries,抛出未捕获的错误

所以,不管是handleError还是captureCommitPhaseError,都会从发生错误的节点的父节点开始,逐层向上遍历,寻找最近的Error Boundaries。

一旦找到,就会构造:

  • 用于执行Error Boundaries API的callback
  • 用于抛出React提示信息的callback
  // ...为了可读性,逻辑有删减
function createClassErrorUpdate() {
  if (typeof getDerivedStateFromError === 'function') {
// 用于执行getDerivedStateFromError的callback
    update.payload = () => {
      return getDerivedStateFromError(error);
};
// 用于抛出React提示信息的callback
    update.callback = () => {
      logCapturedError(fiber, errorInfo);
    };
  }
  if (inst !== null && typeof inst.componentDidCatch === 'function') {
// 用于执行componentDidCatch的callback
    update.callback = function callback() {
      this.componentDidCatch(error);
    };
  }
  return update;
}

如果没有找到Error Boundaries,继续向上遍历直到根节点。

此时会构造:

用于抛出未捕获错误的callback用于抛出React提示信息的callback

// ...为了可读性,逻辑有删减
funffction createRootErrorUpdate() {
  // 用于抛出“未捕获的错误”及“React的提示信息”的callback
  update.callback = () => {
    onUncaughtError(error);
    logCapturedError(fiber, errorInfo);
  };
  return update;
}

执行callback

构造好的callback在什么时候执行呢?

在React中有两个执行用户自定义callback的API:

对于ClassComponent, this.setState(newState, callback)中newState和callback参数都能传递Function作为callback

所以,对于Error Boundaries,相当于主动触发了一次更新:

this.setState(() => {
  // 用于执行getDerivedStateFromError的callback
}, () => {
  // 用于执行componentDidCatch的callback
  //  以及 用于抛出React提示信息的callback
})

对于根节点,执行ReactDOM.render(element, container, callback)中callback参数能传递Function作为callback

所以,对于没有Error Boundaries的情况,相当于主动执行了如下函数:

ReactDOM.render(element, container, () => {
// 用于抛出“未捕获的错误”及“React的提示信息”的callback
})

所以,Error Boundaries的实现可以看作是:React利用已有API实现的新功能。

总结

经常有人问:为什么Hooks没有Error Boundaries?

可以看到,Error Boundaries的实现借助了this.setState可以传递callback的特性,useState暂时无法完全对标。

以上就是React工作流程及Error Boundaries实现过程讲解的详细内容,更多关于React工作流程Error Boundaries实现过程的资料请关注我们其它相关文章!

(0)

相关推荐

  • 封装一个最简单ErrorBoundary组件处理react异常

    前言 从 React 16 开始,引入了 Error Boundaries 概念,它可以捕获它的子组件中产生的错误,记录错误日志,并展示降级内容,具体 官网地址 错误边界避免一个组件错误导致整个页面白屏不能使用等情况,使用优雅降级的方式呈现备用的 UI,错误边界可以在渲染期间.生命周期和整个组件树的构造函数中捕获错误.自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载 ErrorBoundary 意义 某些 UI 崩溃,不至于整个 webapp 崩溃 在浏

  • React中Portals与错误边界处理实现

    目录 Portals 错误边界处理 如果没有使用错误边界会怎样? 注意点 Portals 可以说是 插槽,但 不同于 Vue 中的 slot,它指的是将一个 React 元素渲染到指定的容器 (真实 DOM) 中 比如说,Modal 组件一般默认直接作为 body 的真实结构的子元素渲染出来,那么我们就可以借助 ReactDOM.createPortal(ReactElement, RealDOM container) 创建一个 React 元素,示例代码: import React from

  • 详解React 16 中的异常处理

    详解React 16 中的异常处理 异常处理 在 React 15.x 及之前的版本中,组件内的异常有可能会影响到 React 的内部状态,进而导致下一轮渲染时出现未知错误.这些组件内的异常往往也是由应用代码本身抛出,在之前版本的 React 更多的是交托给了开发者处理,而没有提供较好地组件内优雅处理这些异常的方式.在 React 16.x 版本中,引入了所谓 Error Boundary 的概念,从而保证了发生在 UI 层的错误不会连锁导致整个应用程序崩溃:未被任何异常边界捕获的异常可能会导致

  • React 错误边界组件的处理

    这是React16的内容,并不是最新的技术,但是用很少被讨论,直到通过文档发现其实也是很有用的一部分内容,还是总结一下- React中的未捕获的 JS 错误会导致整个应用的崩溃,和整个组件树的卸载.从 React16 开始就是这样.但是同时React也引入了一个新的概念--错误边界. 定义,是什么 错误边界仍然是一种组件,可以捕获(打印或者其他方式)处理该组件的子组件树任何位置的 JavaScript 错误,并根据需要渲染出备用UI. 工作方式类似于try-catch,但是错误边界只用于 Rea

  • React工作流程及Error Boundaries实现过程讲解

    目录 什么是Error Boundaries 步骤1:捕获错误 步骤2:构造callback 执行callback 总结 这里简单讲解下React工作流程,后文有用.分为三步: 触发更新 render阶段:计算更新会造成的副作用 commit阶段:在宿主环境执行副作用 副作用有很多,比如: 插入DOM节点 执行useEffect回调 好了,让我们进入主题. 什么是Error Boundaries React提供了两个与错误处理相关的API: getDerivedStateFromError:静态

  • React之错误边界 Error Boundaries示例详解

    目录 引言 注意 实现 错误边界应该放置在哪? 未捕获错误(Uncaught Errors)该如何处理? 注意:自 React 15 的命名更改 引言 过去,组件内的代码异常会导致 React 的内部状态被破坏,产生可能无法追踪的错误.但 React 并没有提供一种优雅处理这些错误的方式,也无法从错误中恢复. 默认情况下,若一个组件在渲染期间(render)发生错误,会导致整个组件树全部被卸载,这当然不是我们期望的结果. 部分组件的错误不应该导致整个应用崩溃.为了解决这个问题,React 16

  • React Fiber树的构建和替换过程讲解

    目录 前言 mount 过程 update 过程 前言 React Fiber树的创建和替换过程运用了双缓存技术,即先在内存中创建 fiber 树,待 fiber 树创建完成以后,直接将旧的 fiber 树替换成新的 fiber 树,这样做的好处是省去了直接在页面上渲染时的计算时间,避免计算量大导致的白屏.卡顿,现在你一定还不太理解,下面进行详细讲解! mount 过程 以一下demo为例进行讲解: function App() { const [num, add] = useState(0);

  • react进阶教程之异常处理机制error Boundaries

    目录 Error Boundaries介绍 ComponentDidCatch 参数 触发error boundaries后程序要走向哪里? 对于不能捕获的错误的新处理方式 在堆中跟踪component try/catch 如何? Event Handlers怎么样? React 15后的函数命名改变 总结 该文章翻译自官网 https://reactjs.org/docs/error-boundaries.html 该文章包含以下内容: 1.Error Boundaries介绍 2.Compo

  • React错误边界Error Boundaries

    首先 我们先构建出问题的场景 我们创建一个react项目 然后在src下创建 components 文件夹目录 在下面创建一个 error.jsx 组件 参开代码如下 import React from "react"; export default class App extends React.Component{ constructor(props){ super(props); this.state = { } } render(){ return ( <div>

  • Django中间件工作流程及写法实例代码

    熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截. django中的中间件(middleware)就是类似钩子的一种存在.下面我们来介绍一下,并且给出一些实例. 1.Middleware的工作流程 我盗了一个图,看网上很多人用这个图,来源已经追不明白了.简单声明一下,这个图不是我的.看着图我们分析一下: 1)django的请求相应流程:HttpRequest -> RequestMiddleware -> view function -&

  • openstack云计算keystone组件工作流程及服务关系

    目录 一 什么是keystone 二 为何要有keystone 三 keystone的功能 四 keystone概念详解 第一部分 endpoint举例 V3新增的概念: 第二部分 第三部分 五 keystone内包含的组件 六 keystone与openstack其他服务的关系 七 keystone与其他组件协同工作流程 八 keystone工作流程详解 一 什么是keystone keystone是OpenStack的身份服务,暂且可以理解为一个'与权限有关'的组件. 二 为何要有keyst

  • 详解Redux的工作流程

    目录 Redux理解 redux是什么 什么情况下需要使用redux? redux工作流程图 action reducer store 求和案例——纯react版 求和案例——redux精简版 求和案例——redux完整版 (当然不是这张图) Redux理解 redux是什么 redux是一个专门用于做状态管理的JS库(不是react插件库): 它可以在react.angular.vue等项目中,但基本与react配合使用: 作用:集中式管理react应用中多个组件共享的状态. 什么情况下需要使

  • Git 教程之工作流程详解

    Git 工作流程 本章节我们将为大家介绍 Git 的工作流程. 一般工作流程如下: 1.克隆 Git 资源作为工作目录. 2.在克隆的资源上添加或修改文件. 3.如果其他人修改了,你可以更新资源. 4.在提交前查看修改. 5.提交修改. 6.在修改完成后,如果发现错误,可以撤回提交并再次修改并提交. 下图展示了 Git 的工作流程:

  • python中Pexpect的工作流程实例讲解

    1.工作流程步骤 (1)用spawn来执行一个程序: (2)用expect方法来等待指定的关键字,这个关键字是被执行的程序打印到标准输出上面的: (3)当发现这个关键字以后,使用send/sendline方法发送字符串给这个程序. 2.实例 spawn类 class spawn(SpawnBase): '''This is the main class interface for Pexpect. Use this class to start and control child applica

随机推荐