从“更新”到“页面变更”:一次 setState 的全链路鸟瞰
一句话结论:一次更新从
setState出发,会经历:产生 update → 计算 lane/优先级 → 调度 root → render(workLoop) → commit(落 DOM) → 触发 effects;你只要把每一步对应到“在哪个阶段发生、是否可中断”,就能把并发/批处理/StrictMode/Transition/Suspense 串成一条线。
1. 产生 update:更新从哪里来
- React 合成事件回调
- setTimeout / Promise / 原生事件
- 网络请求回调、订阅回调
更新的本质是“对某个 fiber 的状态变更请求”。
2. 分配优先级:lane / event priority
- React 会把更新来源映射为不同优先级
- 并用 Lane(位图)表示“哪些更新在等着做、谁更重要”
3. 调度:把 root 放进队列
- root 维护 pending/suspended/pinged/expired 等 lanes 集合
- 调度器选择 nextLanes(下一批要渲染的 lanes)
4. Render:workLoop(可中断)
- 深度优先遍历 Fiber
- 单元边界检查
shouldYield() - 可能中断并稍后恢复,或被更高优先级打断重做
5. Commit:落地到 DOM(不可中断)
- mutation:真正改 DOM
- layout effects:读写布局相关副作用
- passive effects:useEffect(异步)
6. 这些“实战特性”分别卡在哪个环节?
- Automatic Batching:在“产生 update → 调度”阶段合并多个更新
- StrictMode(DEV):在 commit 周边额外执行检查流程(模拟卸载/挂载)
- Transition:在“分配优先级”阶段把一类更新放入低优先级 lanes
- Suspense:在 render 阶段挂起(suspend),在边界处选择 fallback
- Error Boundary:在 render/commit 相关链路捕获错误并 fallback
关联阅读
- lane 模型:
../03-concurrent-mode/13-lane-model.md - workLoop:
../03-concurrent-mode/11-workLoop-full.md - React 18 实战目录:
../09-react-18-in-practice/README.md