第
深入理解React?State?原理
目录问题:setState到底是同步还是异步的?类组件statesetState原理揭秘函数组件state
问题:setState到底是同步还是异步的?
如果对React底层有一定了解,可以回答出batchUpdate批量更新概念,以及批量更新被打破的条件。
答案:有时是同步,有时是异步。
在合成事件和生命周期函数里是异步的在原生事件和setTimeout、promise里是同步的
造成setState的异步并不是由内部的异步代码引起的,在本身的执行过程中时同步的,但是合成事件和生命周期函数的调用顺序在更新之前,导致在内部不能直接得到更新后的值,可以用第二个参数callback来获取。
具体解释:可参考setState的执行过程
类组件state
setState(obj,callback)
第一个参数:当obj为一个对象,则为即将合并的state;如果obj是一个函数,那么当前组件的state和props将作为参数,返回值用于合并新的state。第二个参数callback:callback为一个函数,函数执行上下文中可以获取当前setState更新后的最新state的值,可以作为依赖state变化的副作用函数,可以用来做一些基于DOM的操作。
一次事件中触发一次如上setState,在React底层执行过程:
render阶段render函数执行-commit阶段真实DOM替换-setState回调函数执行callback
首先,setState会产生当前更新的优先级(老版本用expirationTime,新版本用lane)。接下来React会从fiberRoot根部fiber向下调和子节点,调和阶段将对比发生更新的地方,更新对比expirationTime,找到发生更新的组件,合并state,然后触发render函数,得到新的UI视图层,完成render阶段。接下来到commit阶段,commit阶段,替换真实DOM,完成此次更新流程。此时仍然在commit阶段,会执行setState中callback函数,到此为止完成了一次setState全过程。
setState原理揭秘
本质:React底层调用Updater对象上的enqueueSetState方法
enqueueSetState():创建一个update,放入当前fiber对象的待更新队列中,最后开启调度更新,进入更新流程。
React的batchUpdate批量更新
目的:多次setstate会让逻辑多停留在js运行层面,阻塞了浏览器绘制,因此需要批量更新
batchedEventUpdates():
分析流程:
React事件执行前通过isBatchingEventUpdates=true打开开关,开启事件批量更新当事件结束,通过isBatchingEventUpdates=false关闭开关在scheduleUpdateOnFiber中根据这个开关来确定是否进行批量更新
1)异步环境下,继续开启批量更新模式:
异步操作里面的批量更新规则会被打破,因此提供了手动批量更新方法:unstable_batchedUpdates
2)提升更新优先级:
提供了方法:flushSync,可以将回调函数中的更新任务,放在一个较高的优先级中优先执行
补充:flushSync在同步条件下,会合并之前的setState|useState
3)总结:React同一级别更新优先级关系是:
flushSync中的setState正常执行上下文中setState异步setTimeout,Promise中的setState
函数组件state
const[state,dispatch]=useState(initData)
①state目的提供给UI,作为渲染视图的数据源②dispatch改变state的函数,可以理解为推动函数组件渲染的渲染函数③initData初始值
initData的初始值
第一种情况是非函数,将作为state初始化的值第二种情况是函数,函数的返回值作为useState初始化的值
dis