setState是同步还是异步

98 阅读2分钟

setState是同步还是异步

1. 在react18中已经全面异步
2. 在之前版本,原生事件是同步,非原生是异步。

原因如下:

React 的更新是基于 Transaction(事务)的,Transacation 就是给目标执行的函数包裹一下,加上前置和后置的 hook ,在开始执行之前先执行 initialize hook,结束之后再执行 close hook,这样搭配上 isBatchingUpdates 这样的布尔标志位就可以实现一整个函数调用栈内的多次 setState 全部入 pending 队列,结束后统一 apply 了

这么做的好处是可以同时批处理很多setState的其他操作,不用每次都去更新。

为什么原生事件可以同步 原生事件如setTimeOut或者直接获取dom绑定事件是同步的,是因为react的事件(指的是onClick啊之类的jsx上绑定的事件)是被整体劫持分发的,上述的包装是在劫持分发过程中进行的,所以我们用原生事件,react无法包装,就会立即执行。

3. react的事件是合成事件((Synethic event),不是原生事件。简单如下

image.png

合成事件分为以下三个主要过程:

一 事件注册 所有事件都会注册到document上,拥有统一的回调函数dispatchEvent来执行事件分发

二 事件合成 从原生的nativeEvent对象生成合成事件对象,同一种事件类型只能生成一个合成事件Event,如onclick这个类型的事件,dom上所有带有通过jsx绑定的onClick的回调函数都会按顺序(冒泡或者捕获)会放到Event._dispatchListeners 这个数组里,后面依次执行它

三 事件派发 每次触发事件都会执行根节点上 addEventListener 注册的回调,也就是 ReactEventListener.dispatchEvent 方法,事件分发入口函数。该函数的主要业务逻辑如下:

找到事件触发的 DOM 和 React Component 从该 React Component,调用 findParent 方法,遍历得到所有父组件,存在数组中。 从该组件直到最后一个父组件,根据之前事件存储,用 React 事件名 + 组件 key,找到对应绑定回调方法,执行,详细过程为: 根据 DOM 事件构造 React 合成事件。 将合成事件放入队列。 批处理队列中的事件(包含之前未处理完的,先入先处理)