React底层原理
一句话总结:
- React = 组件化 + 声明式 UI + 单向数据流,通过虚拟 DOM、Diff、Fiber 调度与批处理,把不可预测的 DOM 更新过程变成可预测、可中断、可优化的渲染流水线。
核心理念
- 组件化: UI 拆分为可复用的组件,组件由
props和state决定输出。 - 声明式 UI: 你描述“界面应该是怎样的”,React 负责“如何更新到这个样子”。
- 单向数据流: 数据从父到子流动,便于推理与调试。
- 最小可变性: 尽量用不可变数据(便于浅比较和跳过渲染,即如果引用没有变化,则React 会直接复用已有 Fiber 和 DOM)与纯函数思想,减少副作用。
工作机制(从输入到界面)
- 触发更新: 调用
setState/useState、useReducer或父组件props变化。 - 调度与批处理: React 调度器对更新分优先级,可能合并多次更新(批处理)。
- 渲染阶段(计算):
- 计算新的组件树(虚拟树),执行函数组件体,收集 hooks 调用结果。
- 通过 Diff(协调)找出和上一次的差异,生成最小变更集。
- 提交阶段(应用):
- 将差异一次性提交到真实 DOM(或原生宿主,如 React Native),触发必要的副作用。
- 执行布局/副作用(如
useLayoutEffect、useEffect)。
原理要点
-
声明式UI与组件化:
- 声明式UI: 在 React 中,你只需要描述应用在给定状态下应该呈现的样子。当状态改变时,React 会自动计算出需要进行的更改,而不是手动操作DOM元素。
- 组件化: 整个应用由独立的、可复用的组件构成,每个组件管理自己的状态(state)和属性(props)。这种模块化使得代码更易于管理和维护。
-
虚拟 DOM(VNode/Element):
虚拟DOM是一个轻量级的JavaScript对象树,它是真实DOM结构的一个内存表示。每次组件状态(state)发生变化时,React 会生成一个新的虚拟DOM树。它避免了直接、频繁地操作昂贵的真实DOM,从而提高了性能。 -
协调机制 (Reconciliation) 与 Diff 算法:
这是React高效更新的关键所在:- Diff 算法: React 会对比新旧两棵虚拟DOM树的差异。
- 对比新旧 Fiber 树:
- key 不变且 type 相同 → 复用节点,更新 props。
- key 或 type 改变 → 卸载旧节点,创建新节点。
- 对比新旧 Fiber 树:
- 高效更新: 通过一系列启发式算法(如比较相同位置的元素类型、使用 key 属性等),React 能够找出两棵树之间最小的差异集合(即需要更新的部分)。
- 批量更新: 找到差异后,React 会将这些必要的更改批量应用到真实的DOM上,而不是逐个更新,从而最大限度地减少浏览器重排和重绘。
- Diff 算法: React 会对比新旧两棵虚拟DOM树的差异。
-
Fiber 架构与任务调度:
从 React 16 开始,引入了 Fiber 架构:- 异步可中断更新: Fiber 架构将渲染任务拆分为多个小单元,并根据优先级进行调度。这意味着 React 可以在渲染过程中暂停工作,让浏览器处理更高优先级的任务(如用户输入、动画),然后再恢复渲染。这使得用户界面响应更流畅,改善了用户体验。
- 优先级机制: 不同的更新可以有不同的优先级。例如,用户输入的响应优先级高于后台数据更新
什么是 React Fiber
Fiber 节点(Fiber node)本质上是一个普通的 JavaScript 对象。用于管理React 内部组件和DOM元素相关信息、调度更新工作的内部数据结构。
- 定义: Fiber 是 React 16+ 引入的新的内部架构与数据结构(Fiber node),用于实现可中断、可恢复、分片的渲染与更细粒度的优先级调度。
- 目标: 时间分片与可中断渲染、优先级调度(让高优先级交互优先)、更好地处理动画/交互、改进错误边界与异步渲染(Suspense)。
举例:
比如我有这么一个jsx,会有几个React Fiber?
<div><Content />
</div>funciton Content() {return <h1>你好</h1>
}

为什么需要 Fiber
Fiber 使用页面更新更流畅、响应速度更快,通过了更好的用户体验。 它将 React 的更新逻辑从一个不可控的、同步的“跑到底”过程,变成了一个可控的、可中断的、高优先级的智能调度系统,使得 React 应用在复杂场景下依然能保持高性能。
- 经典递归渲染不可中断,遇到大树时会卡住主线程。
- Fiber 将递归改为可中断的循环+链表结构,支持时间切片与调度,提升交互流畅度。
Fiber 节点(Fiber node)本质
- 每个将要渲染的元素(DOM 节点或组件)对应一个 Fiber 节点。
- 常见重要字段(简化理解):
type: 组件类型(函数/类)或内置标签字符串(如'div')。tag: 节点种类(函数组件、类组件、HostComponent等)。pendingProps/memoizedProps: 本次待生效的 props / 上次生效的 props。stateNode: 实例引用(类组件实例或真实 DOM 节点)。child/sibling/return: 构成 Fiber 树的单向链表结构。flags(旧称 effectTag): 标记需要在 commit 阶段执行的副作用。lanes/priority: 更新优先级。updateQueue: 挂起的状态更新队列(setState/useState 等)。
与你当前报错的关系
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method ofModalTrend. atcreateFiberFromTypeAndProps(react-dom.development.js:28478:1)
- 报错栈里的
createFiberFromTypeAndProps就是“根据 Element 的type和props生成 Fiber”的入口之一。 - 如果 JSX 里的组件未正确导入,
type会是undefined,在创建 Fiber 时即抛错。你这里的Modal/ModalHeader/ModalContent就是典型案例。
常见面试/排障要点
- 小写标签编译成
'div'这类字符串 → HostComponent → Fiber 会创建 DOM 节点。 - 大写标签编译成变量(函数/类)→ Function/ClassComponent → Fiber 会执行函数或实例化类。
- 并发特性(Concurrent Rendering)不是并发线程,而是可中断/分片的合作式调度。
- Suspense/Transition 基于 Fiber 的优先级与挂起机制工作。
如果你想更直观地观察 Fiber 行为,建议在开发工具中开启 “Highlight updates” 或使用 Profiler,能看到分片提交与优先级带来的差异。
