React 可中断恢复
社区来稿 · Liu由用户发布,不代表 batype 本人观点
例子+图解+流程说明,帮你理解高优先级任务如何中断、恢复,以及 workInProgress 树的构建过程。
场景举例#
假设有如下组件树:
<App>
<A />
<B />
<C />
</App>
-
用户在 A 组件中输入内容(低优先级,startTransition 包裹)。
-
渲染到 B 组件时,用户突然点击了 C 组件的按钮(高优先级)。
1. 初始渲染(低优先级)#
-
React 开始构建 workInProgress 树,从 -> -> -> 。
-
由于是低优先级(比如 startTransition),React 每处理一部分 Fiber 节点就会“让出”控制权,检查是否有更高优先级任务。
2. 中断发生#
-
当 React 渲染到 时,用户在 上触发了高优先级事件(比如点击)。
-
React 检查到有高优先级任务到来,中断当前的 workInProgress 构建,把控制权交还给浏览器,优先处理高优先级事件。
3. 高优先级任务插队#
-
React 以高优先级开始处理 的点击事件,可能会触发 组件的 setState。
-
这时,React 会判断:
-
如果 的更新和之前的 workInProgress 树没有冲突,可以在原有 workInProgress 树基础上继续构建(恢复)。
-
如果有冲突(比如 的更新影响了 或 ),则丢弃当前 workInProgress 树,重新从 current 树生成新的 workInProgress 树。
-
4. 恢复渲染#
-
假设 的更新只影响自己,React 会把高优先级的更新插入到 workInProgress 树的 节点。
-
React 继续遍历 workInProgress 树,从中断点( 后)恢复,完成剩余节点的构建。
5. 图解(Mermaid)#
graph TD
A1["<App> (current)"]
A2["<A> (current)"]
A3["<B> (current)"]
A4["<C> (current)"]
B1["<App> (workInProgress)"]
B2["<A> (workInProgress)"]
B3["<B> (workInProgress)"]
B4["<C> (workInProgress)"]
A1 --> A2 --> A3 --> A4
B1 --> B2 --> B3 --> B4
subgraph 渲染阶段
B1
B2
B3
B4
end
click B3 "中断点"
click B4 "高优先级插队"
6. 伪代码流程#
// 1. 低优先级渲染
workInProgress = createWorkInProgress(current, lowPriorityUpdate);
beginWork(workInProgress); // 渲染<App>、<A>、<B>
// 2. 检查到高优先级任务
if (hasHighPriorityTask) {
// 3. 判断是否可以复用workInProgress
if (canReuseWorkInProgress(workInProgress, highPriorityUpdate)) {
// 4. 合并高优先级更新,恢复渲染
mergeUpdate(workInProgress, highPriorityUpdate);
resumeWork(workInProgress, from: interruptedPoint);
} else {
// 5. 丢弃,重建workInProgress
workInProgress = createWorkInProgress(current, highPriorityUpdate);
beginWork(workInProgress);
}
}
7. 总结#
-
React 渲染 workInProgress 树时,遇到高优先级任务会中断。
-
如果新旧任务能合并,workInProgress 树会被复用,恢复渲染。
-
如果不能合并,则丢弃当前 workInProgress,重新构建。
-
这种机制让 React 能灵活响应用户操作,提升体验。