在React
中,setState
既可以是同步的也可以是异步的,这取决于执行时机和执行的上下文
[1]. setState
的异步并不是指内部由异步代码实现的,实际上执行的过程和代码都是同步的,只是合成事件和钩子函数调用的顺序在更新之前,导致在合成事件和钩子函数中不能立即看到state
的变化,而在原生事件和setTimeout
中,setState
是同步的
[2]. 在React17
中,setState
是批量执行的,因为执行前会设置executionContext
,但如果在setTimeout
,事件监听器等函数中,就不会设置executionContext
的,这时候setState
会同步执行,可以在外面包一层batchUpdates
函数,手动设置下excutionContext
来切换成异步批量执行
[3]. 在React
的渲染流程中,setState
会创建update
对象挂到fiber
对象上,然后耨调度performSyncWorkOnRoot
重新渲染,一个主要任务的先后顺序是:render
阶段render
函数执行-->commit
阶段真实DOM
替换--->setState
回调函数执行callback
,因此,可以看出setState
的执行顺序是在render
之后,commit
之前
[4]. 如果ExecutionContext
为0,表示当前没有正在进行的其他任务,则setState
是同步的,在React
的源码中,当ExecutionContext
为0时,setState
是同步的
[5]. 批量更新:多个顺序的setState
不是同步的一个一个执行的,而是会一个一个加入队列,然后最后一起执行,在合成事件和生命周期钩子中,setState
更新队列时,存储的是合并状态,因此,前面设置的key
值会被后面的覆盖,最终只会执行依次更新
综上所述,setState
既可以是同步的也可以是异步的,具体取决于执行时机和执行的上下文,在React
中,如果需要手动控制setState
的异步执行
也就是在合成事件和生命周期函数中是异步的,在原生事件和定时器中都是同步的,setState
本身不分同步或异步,而是取决于是否处于batch update
中
可以使用batchUpdates
函数手动设置excutionContext
来切换成异步批量执行,同时,在合成事件和生命周期钩子中,setState
更新队列时,会存储合并状态,因此需要注意key
值的覆盖问题
(添加社群,拓展人脉圈子)
JS面试题18-说一说网页当中性能优化有哪些性能指标,如何量化
2023-03-14
JS面试题17-比较一下服务端渲染与客户端渲染
2023-03-12
JS篇面试题16-Es6中的事件扩展符在什么场景下使用
2023-03-11
框架篇-面试题6-说一下Vue2与Vue3的钩子函数
2023-03-09
一文了解互联网中的运营
2023-03-03