面试官:“聊聊 React Fiber 吧。”
你:“呃……就是 Fiber……一种数据结构?”
面试官微笑,你原地社死。
别慌,看完这篇,你就能把 Fiber 讲成故事,还能顺手画出它的架构图。
一、为什么 15 代的 React 会“卡”?
在 React 15 及更早版本, reconciliation(协调)过程是同步、不可中断的。
浏览器主线程被 React 一把梭哈:
- 计算新 Virtual DOM
- 和旧树 diff
- 一口气把差异 patch 到真实 DOM
页面元素少时还好;一旦组件层级深、节点多,主线程就被长时间霸占,用户输入、动画、滚动全部“卡死”。
痛点总结:同步渲染 = 一旦开始,停不下来。
二、Fiber 的解题思路:把“一口气”拆成“一小口”
React 16 引入的 Fiber 架构,核心只有三句话:
- 把渲染任务拆成“工作单元”(unit of work)
- 允许工作单元被中断、恢复、甚至丢弃
- 让浏览器拿回主线程,优先处理高优任务(如用户输入)
用“装修房子”类比 :
- 旧 React:一口气装完客厅+卧室+厨房,期间业主敲门都听不见。
- Fiber:把每间房拆成独立任务卡,随时可停工去开门,回来再继续。
三、Fiber 节点长啥样?——一张“任务卡”的解剖
每个 JSX 元素都会被编译成一个普通的 JavaScript 对象,即 fiber 节点。
核心字段(简化版):
fiber = {
type, // 'div' | MyComponent | Fragment …
key, // 同级 diff 的“身份证”
stateNode, // 对应的 DOM 节点或组件实例
return, // 指向“父亲”
child, // 指向“长子”
sibling, // 指向“下一个兄弟”
pendingProps, // 新来的 props
memoizedProps, // 上一次渲染用的 props
memoizedState, // 上一次渲染用的 state(Hooks 链表就挂在这)
alternate, // 指向“另一棵树”上的自己,实现双缓冲
flags, // 副作用标记(增 / 删 / 改)
nextEffect, // 副作用链表指针
lanes, // 优先级车道
}
看见没?fiber 节点 = 虚拟 DOM 节点 + 调度信息 + 副作用信息 + 双缓冲指针
它既是“数据”,也是“待办事项”。
四、双缓冲:画好“新图纸”再一次性贴到墙上
Fiber 维护两棵树:
- current:屏幕正在显示的旧树
- workInProgress(WIP):内存中正在构造的新树
- 所有更新先在 WIP 树上“草稿”
- 等整棵树计算完毕,进入commit 阶段,一次性把差异 patch 到真实 DOM
- 树切换:root.current = WIP,旧树变“备胎”
好处:用户永远看不到“半成品”界面,也省去中间状态的回滚成本 。
五、Render vs Commit:能暂停的和不能暂停的
| 阶段 | 是否可中断 | 做的事 | 类比装修 |
|---|---|---|---|
| Render | ✅ 可中断 | 构建 WIP 树,diff,打副作用标记 | 画新图纸,可停笔 |
| Commit | ❌ 不可中断 | 操作真实 DOM,触发生命周期 / useEffect | 贴瓷砖,必须一口气 |
六、优先级车道(Lanes)——“业主说先装厨房”怎么办?
React 把更新按紧急程度拆成 32 条车道:
- 输入 / 点击 → 高优(同步车道)
- 列表渲染 / 数据同步 → 低优(空闲车道)
高优任务可以插队低优任务;被插队的低优任务回到 WIP 池,等下次空闲继续。
这就是 useTransition、startTransition 的底层依赖 。
七、工作循环:浏览器给 React“发饷”——一帧一帧领工资
function workLoop(deadline) {
while (nextUnitOfWork && deadline.timeRemaining() > 0) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
if (!nextUnitOfWork) {
// WIP 树构建完成,进入 commit
commitRoot();
} else {
// 没干完,下帧继续
requestIdleCallback(workLoop);
}
}
performUnitOfWork:处理一个 fiber 节点,返回“下一个节点”requestIdleCallback:浏览器空闲时再把主线程“租”给 React
协作式调度:React 不抢,浏览器给多少时间干多少活,用户永远优先。
八、从 Fiber 到并发特性:Suspense、useTransition 诞生记
Fiber 只是“基建”,上层长出了:
- 时间切片(Time-slicing):把长列表拆成多帧渲染
- Suspense:组件“等数据”时先不进入 commit,避免白屏
- useTransition:把 setState 标记为可中断,低优更新不堵高优输入
这些特性共同构成 React 18 的 Concurrent Rendering。
九、面试“秒答”模板:背下来,再讲出故事
Q:什么是 React Fiber?
A:
Fiber 是 React 16 起全新的协调引擎,它把原本同步不可中断的渲染过程拆成可暂停 / 恢复 / 优先级排序的小任务。
每个 React 元素对应一个fiber 节点,节点以链表形式串联成树,并通过双缓冲机制在内存中构建新树,再一次性提交。
这使得 React 能在不阻塞主线程的前提下完成大型更新,也为 Suspense、useTransition 等并发特性打下基础。
十、30 秒手绘知识脑图(文字版)
Fiber 节点
├─ 数据层:type/key/props/state
├─ 链接层:return/child/sibling
├─ 副作用:flags + nextEffect 链表
├─ 双缓冲:alternate 指针
└─ 优先级:lanes 车道
Render 阶段(可中断)
↓
commit 阶段(同步执行)
↓
Concurrent 特性
十一、总结:记住三句话,Fiber 永不慌
- Fiber = 工作单元 + 链表树 + 双缓冲
- Render 可中断,Commit 必同步
- 没有 Fiber,就没有并发特性,也没有不卡的主线程
下次再被问到“React Fiber 是什么?”
别背定义,讲故事。
从“装修房子”讲起,再甩三个核心点,面试官会眼前一亮。
如果本文对你有帮助,点个 赞 并 分享 给正在准备面试的小伙伴吧!