Bootstrap

setState是同步更新还是异步更新

先说结论

React18之前:使用了ReactDOM.rendersetStateReact调度流程中是异步更新,在原生事件和setTimeout中是同步更新。
React18:使用ReactDOM.createRoot,默认都是批量更新,也就是异步更新。

React18之前,setState在原生事件和定时器中是同步的,在合成事件和生命周期函数里面是异步的,原理在于合成事件和生命周期函数调用顺序在批处理和更新之前,导致在合成事件和生命周期函数里没法立刻拿到更新后的值,导致形成所谓的异步

setState为什么设计为异步

1. 提升性能
如果每次调用setState都进行一次更新,意味着render函数会被频繁调用,界面重新渲染,最好的方法就是获取到多个更新之后,批量进行更新
2. 保持state和props同步
如果同步更新了state,但是还没有执行render函数,那么stateprops不能保持同步

react18之前为什么不确定是同步还是异步呢

React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state;如果是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生事件处理,调用setState会同步更新this.state

为什么会出现以上有时同步,有时异步的现象呢

  1. ReactsetState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,
  2. isBatchingUpdates默认是false,也就表示setState会同步更新this.state
  3. 但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true
  4. 而当React在调用事件处理函数之前就会调用这个batchedUpdates,从而react控制的事件处理过程setState不会同步更新this.state
  5. 即:setState的“异步”并不是说内部由异步代码实现的,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,
  6. 当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。

react18之后setState有哪些改动

  • react18之后,setState都会表现为异步(即批处理)。
  • 批处理:是指 React将多个状态更新分组到单个重新渲染中以获得更好的性能
  • 如果同一点击事件中有两个状态更新,React 总是将它们批处理为一次重新渲染。
;