第十三章 React高优打断低优、饥饿问题(React18源码解析十三)

141 阅读2分钟

第一章 JSX(React18源码解析一)
第二章 实现Virtual DOM(React18源码解析二)
第三章 根节点关联根Fiber(React18源码解析三)
第四章 初始化UpdateQueue、添加update(React18源码解析四)
第五章 实现时间切片函数和拷贝Fiber(React18源码解析五)
第六章 构建FiberTree(React18源码解析六)
第七章 commit(React18源码解析七)
第八章 React中的事件(React18源码解析八)
第九章 useReducer、useState(React18源码解析九)
第十章 React的dom diff(React18源码解析十)
第十一章 React的Effect(React18源码解析十一)
第十二章 React的同步、并发渲染(React18源码解析十二)
第十三章 React高优打断低优、饥饿问题(React18源码解析十三)

高优打断低优、饥饿问题详解

饥饿问题是由高优打断低优引起的,而高优打断低优只会存在于并发渲染过程中。有四个关键点

1.Scheduler_scheduleCallback返回task,为当前的执行的任务并挂载到root.callbackNode,当有新的setState执行ensureRootIsScheduled时,检测到root.callbackNode上有挂载的task时,调用cancelCallback(root.callbackNode),即高优打断低优

2.第一个要点说明了高优打断低优,此时带来一个问题被打断的低优task什么时候执行。当高优渲染fiber tree构建完毕,进入到commit阶段,为了防止被打断的低优task未执行,会在commitRootImpl执行末尾重新调用一次ensureRootIsScheduled并传入当前时间

3.因为重新调用ensureRootIsScheduled,且低优lane在root.lanes上还未被清除,此时拿到的最高优先级lane就是之前被打断的低优lane,会根据此lane创建一个task添加到最小堆等到Scheduler调用,当调用此task.callback即performConcurrentWorkOnRoot时会判断是由有过期task即饿死task,有即会走renderRootSync

4.调用setState创建的update是同步添加的,而Scheduler是异步调用的,即Scheduler调用时hook.queue.pending上有所有的update,当执行updateReducer是会判断updateLane是否是renderLane的子集,来决定是否执行该update,跳过的低优update会保存下来,从而保证被打断的低优lane和饿死lane的执行,二者其实是一回事

高优打断低优、饥饿问题关键步骤

1.上述关键点之1、2、3点和第十二章中提及的步骤相同

2.第四点可查看updateReducer函数(react-main/packages/react-reconciler/src/ReactFiberHooks.js)