深入理解React Fiber机制

 更新时间:2026年06月11日 08:19:42   作者:卷帘依旧  
React Fiber 是 React 16 引入的核心协调算法重构,它解决了旧版 Stack Reconciler 的不可中断、同步递归导致的卡顿问题,下面就来详细的介绍一下

React Fiber 是 React 16 引入的核心协调算法重构,它解决了旧版 Stack Reconciler 的不可中断、同步递归导致的卡顿问题。

简单来说:Fiber 让 React 的渲染过程从「一口气干完」变成了「可中断、可分片、可优先级排序」的任务调度。

下面从三个关键维度展开:

一、为什么需要 Fiber?(痛点分析)

旧版 React(<16)的 Stack Reconciler 有致命缺陷:

  • 同步递归:遍历整个虚拟 DOM 树时,一旦开始就无法停止。
  • 阻塞主线程:如果组件层级很深(几百个),一次更新可能占用 100ms+ 的 JS 执行时间。
  • 导致掉帧:浏览器需要 16.6ms 渲染一帧(60fps),而 React 长期霸占主线程,用户点击、动画都会卡顿。

典型案例:一个输入框绑定大列表更新,每次按键都重新渲染整个列表,造成明显延迟。

Fiber 的目标就是:把同步不可中断的工作,拆解成异步可中断的小任务单元

二、Fiber 的核心机制

1. Fiber 是什么?(数据结构 + 工作单元)

Fiber 既是数据结构,也是执行单元

作为数据结构:每个 React 元素对应一个 Fiber 节点,构成 Fiber 树(链表结构,而非树)。

// Fiber 节点的核心字段
{
  tag: 5,               // 节点类型(函数组件、类组件、DOM等)
  key: null,
  type: 'div',
  return: parentFiber,  // 指向父 Fiber(完成后的返回目标)
  child: childFiber,    // 指向第一个子 Fiber
  sibling: siblingFiber,// 指向下一个兄弟 Fiber
  pendingProps: {},     // 新传入的 props
  memoizedProps: {},    // 上次渲染的 props
  memoizedState: null,  // 上次渲染的 state(用于 Hooks)
  alternate: null,      // 双缓存中的另一个 Fiber(current <-> workInProgress)
}

作为执行单元:Fiber 节点记录了自身的「进度信息」,React 可以在中断后从任意 Fiber 继续工作。

2. 双缓存机制(Double Buffering)

React 维护两棵 Fiber 树:

  • current 树:当前屏幕上显示的内容(已提交到 DOM)。
  • workInProgress 树:在内存中构建的新树,代表下一次要显示的界面。

工作流程:

  1. 触发更新时,克隆 current 树生成 workInProgress 树。
  2. 在 workInProgress 树上进行协调(diff + 标记副作用)。
  3. 构建完成后,commitRoot 将 workInProgress 树切换为 current 树(一次指针切换)。
  4. 复用 alternate 属性指向另一棵树,节省内存分配。

好处:可以在构建过程中随时放弃 workInProgress 树,不影响用户当前看到的界面。

3. 调度与优先级(Scheduler)

Fiber 搭配了独立的调度器(Scheduler),实现了时间切片和优先级队列。

  • 任务拆分:将协调过程拆解为多个「工作单元」(每个 Fiber 节点的处理就是一个单元)。
  • 时间切片:每次循环检查是否还有剩余时间(shouldYield),超时则中断并让出主线程。
  • 优先级机制
    • 离散事件(click、input):立即同步执行(最高优先级)。
    • 连续事件(scroll、拖拽):下一帧之前执行(高优先级)。
    • 数据请求(useEffect、Suspense fallback):可中断的低优先级
    • startTransition 标记的更新:最低优先级,空闲时执行。

简单模拟调度流程:

// 简化的 workLoop
function workLoop(deadline) {
  let shouldYield = false;
  while (nextUnitOfWork && !shouldYield) {
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork); // 处理一个 Fiber
    shouldYield = deadline.timeRemaining() < 1;         // 剩余时间不足 1ms 则中断
  }
  if (nextUnitOfWork) {
    requestIdleCallback(workLoop); // 有空闲时间再继续
  } else {
    commitRoot(); // 全部完成,提交 DOM
  }
}
requestIdleCallback(workLoop);

三、Fiber 架构下的两个阶段

React 将渲染过程拆解为两个截然不同的阶段:

阶段执行内容是否可中断是否执行副作用常见方法
Render/Reconciliation构建 Fiber 树、计算 diff、标记副作用✅ 可中断rendershouldComponentUpdate、hooks 中的更新计算
Commit将副作用应用到真实 DOM、执行生命周期❌ 不可中断componentDidMountuseLayoutEffectref 更新

重要区别

  • Render 阶段可以被打断(比如用户点击新的高优先级事件),React 会丢弃当前 workInProgress 树,重新开始。
  • Commit 阶段必须同步完成,确保 DOM 一致性和用户看到的结果。

这也解释了为什么 componentWillMountcomponentWillUpdate 被标记为不安全 —— 它们可能在 Render 阶段被多次调用或中断。

四、Fiber 带来的具体能力

  1. Concurrent Mode(并发模式,现为默认启用):渲染和用户输入并行处理,不再互相阻塞。
  2. Suspense:等待异步数据(代码、图片、数据)时,渲染 fallback,数据就绪后继续 Fiber 工作。
  3. useDeferredValue / startTransition:将低优先级更新标记为可中断,保障高优先级响应的流畅度。
  4. 错误边界:通过 componentDidCatch 捕获子组件树的错误,防止整个应用崩溃。

五、常见面试追问与简答

Q:Fiber 架构下的 diff 算法有变化吗?
A:核心策略相同(同级比较、key 复用),但实现上基于 Fiber 链表,且 diff 过程是异步可中断的。

Q:Fiber 有打破 React 声明式编程的范式吗?
A:没有。Fiber 是内部实现优化,对外 API 保持一致,开发者依然面向状态编程。

Q:使用 Fiber 一定能提升性能吗?
A:不一定。对于简单应用,Fiber 的调度开销可能略微增加总耗时。主要收益是在复杂交互场景(输入框 + 大列表渲染)下保持 UI 流畅。

Q:Fiber 树和虚拟 DOM 树是什么关系?
A:虚拟 DOM 是 React 元素树(每次 render 重建)。Fiber 树是持久化的(只更新属性),通过 alternate 复用节点,性能更高。

如果你需要进一步了解 Fiber 的副作用收集(Effect List)Hooks 在 Fiber 上的存储原理,我可以继续展开。

到此这篇关于深入理解React Fiber机制的文章就介绍到这了,更多相关React Fiber 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React Native 使用Fetch发送网络请求的示例代码

    React Native 使用Fetch发送网络请求的示例代码

    本篇文章主要介绍了React Native 使用Fetch发送网络请求的示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Electron+React进行通信的方法

    Electron+React进行通信的方法

    electron其实是一个桌面应用程序,不是一个标准的前端web程序,所有没有什么请求的发生,控制台network看不到请求,而是只能通过console.log去打印查看,而且通信协议使用的不是http而是gRPC协议,这篇文章主要介绍了Electron+React如何进行通信,需要的朋友可以参考下
    2022-06-06
  • antd+react中upload手动上传单限制上传一张

    antd+react中upload手动上传单限制上传一张

    本文主要介绍了antd+react中upload手动上传单限制上传一张,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 使用React代码动态生成栅格布局的方法

    使用React代码动态生成栅格布局的方法

    这篇文章主要介绍了使用React简短代码动态生成栅格布局的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • JavaScript中的useRef 和 useState介绍

    JavaScript中的useRef 和 useState介绍

    这篇文章主要给大家分享的是 JavaScript中的useRef 和 useState介绍,下列文章,我们将学习 useRef 和 useState hook是什么,它们的区别以及何时使用哪个。 这篇文章中的代码示例将仅涉及功能组件,但是大多数差异和用途涵盖了类和功能组件,需要的朋友可以参考一下
    2021-11-11
  • 关于react中useCallback的用法

    关于react中useCallback的用法

    这篇文章主要介绍了关于react中useCallback的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • React中组件间数据共享的多种方案

    React中组件间数据共享的多种方案

    在现代前端开发中,React以其组件化思想为核心,极大地提升了代码的可复用性和可维护性,随着应用复杂度的提升,一个不可避免的问题浮出水面:如何在不同组件间高效、清晰、可预测地共享数据,本文将全面、深入地探讨React中组件间数据通信的各种方法
    2025-09-09
  • 深入对比三种主流的React状态管理方案(Redux Toolkit vs Zustand vs Context API)

    深入对比三种主流的React状态管理方案(Redux Toolkit vs Zustand vs Contex

    在现代React开发中,状态管理是构建复杂应用程序的核心挑战之一,本文将深入对比三种主流的React状态管理方案,Redux Toolkit、Zustand和Context API,希望对大家有所帮助
    2025-09-09
  • 深入理解React 三大核心属性

    深入理解React 三大核心属性

    本文主要介绍了React 三大核心属性,主要包括State属性,Props属性,Refs属性,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • React中props使用教程

    React中props使用教程

    props是组件(包括函数组件和class组件)间的内置属性,用其可以传递数据给子节点,props用来传递参数。组件实例化过程中,你可以向其中传递一个参数,这个参数会在实例化过程中被引用
    2022-09-09

最新评论