React 在 layoutEffect 中执行同步更新状态的纠正 flushSyncCallbackQueue 调用时机

352 阅读1分钟

问题

在看 react 源码(17.0.2版本)中看到这样的一段,当时觉得好奇,就调试了下,发现跟描述的不一致。 出处: react.iamkasong.com/renderer/pr… image.png

测试Demo

Demo: image.png

调试流程

实际调试下,并不是在 commitRootImpl 中去实现同步刷新,而是在 setState 的实现中,去重新调用了 scheduleUpdateOnFiber(图1),并优先级是 IMMEDIATE_PRIORITY_TIMEOUT, 并在 ensureRootIsScheduled 创建一个 performSyncWorkOnRootsyncQueue 同步更新数组(图2)。进一步调试会发现走到(图3),并没有在 commitRootImpl 中执行 flushSyncCallbackQueue 方法。而是返回了,最后是在 unbatchedUpdates 中去执行了 flushSyncCallbackQueue 来调用 syncQueue (其中的 performSyncWorkOnRoot),并触发 renderRootSync(也就是 workLoopSync),进去 performUnitOfWork 调度阶段, 最后再重新回到 commitRoot(由于是新的一轮 update, 产生的 effectList 是对应 state 所改变的 Fiber),再执行完更新 dom 后,渲染出来页面。 图1: image.png 图2: image.png 图3: image.png 图4: image.png

总结

  1. 在 commit 阶段触发的更新,都会是 performSyncWorkOnRoot 并立即更新的优先级,并重新触发 commitRoot 继续渲染。
  2. 批量或许同步更新下,都会 flush 新增的同步更新。

image.png

image.png