Skip to content

React Fiber 是什么? ​

Fiber 是 React 的工作单元。每个组件实例对应一个 Fiber 节点。渲染被拆成很多小段,高优先级更新(例如输入)可以打断低优先级更新,最后一次性地把结果提交到 DOM。

原理 ​

Fiber 节点之间用 child、sibling、return 连成树,方便暂停后从中间继续。同时存在两棵树:屏幕上的 current,以及正在算的 workInProgress。算完后两者互换,这是双缓冲。

更新分成两个阶段:

  1. 渲染阶段可以打断。React 根据类型和 key 决定复用、移动还是卸载,并算出这份 Fiber 上的状态。这个阶段不改 DOM,算到一半丢掉也安全。
  2. 提交阶段同步执行。这里才插入、更新、删除 DOM,然后跑 useLayoutEffect。提交不能做一半,否则屏幕上会是不完整的界面。useEffect 在绘制之后异步执行。

优先级用 lane 表示。点击、输入这类离散事件优先;startTransition 里的更新优先级低,可以被新的输入打断。useDeferredValue 让一份派生值停留在旧数据上,等紧急更新画完再跟上。

setState 是往调度器里放一个更新,不是当场把整棵树算完。React 18 的并发特性建立在「渲染阶段可以重来」之上。

追问 ​

和虚拟 DOM diff 是什么关系?

diff 是比较策略:同层、看类型和 key。Fiber 是执行这套策略的数据结构,并加上了可中断的调度。见 虚拟 DOM。

为什么提交阶段不能中断?

渲染阶段只产生计算,用户看不见。提交阶段在改真实 DOM。中断会让界面停在旧节点和新节点混在一起的状态。

易错点 ​

  • Fiber 不是「新的虚拟 DOM 库」,虚拟 DOM 仍然是那棵描述 UI 的树。
  • 渲染阶段可能执行多次,所以渲染期间的函数必须能重入,不要在渲染函数里发请求或改外部变量。副作用放进 effect。
  • startTransition 不会取消更新,它只是让这次更新可以被打断、稍后再画。

相关 ​