⚛️ React Reconciler 协调过程

深度解析 Fiber 树协调的核心原理

基于 React 源码深度解析
2026-03-15 | 技术深度解读

📑 目录

第一部分:基础架构

  • Reconciler 简介
  • 协调过程架构
  • 核心三阶段

第二部分:核心数据结构

  • FiberNode 结构
  • FiberRoot 结构
  • WorkTag / Flags / Lane

第三部分:核心函数

  • beginWork / completeWork
  • commitWork
  • reconcileChildFibers

第四部分:调度与优化

  • WorkLoop 机制
  • 时间切片
  • 性能优化策略

⚛️ Reconciler 简介

Reconciler(协调器) 是 React 渲染架构的核心,负责决定哪些组件需要更新以及如何更新。

核心职责

  • 比较新旧 Fiber 树
  • 计算最小更新集合
  • 标记副作用(Flags)
  • 协调子节点
  • 处理优先级调度

设计目标

  • 增量渲染(可中断)
  • 优先级调度
  • 并发模式支持
  • Suspense 集成
  • 错误边界处理

🏗️ 协调过程架构

┌─────────────────────────────────────────────┐
│              React 渲染架构                  │
├─────────────────────────────────────────────┤
│  Scheduler (调度器)                          │
│    ↓ 调度任务                                │
│  ┌─────────────────────────────────────────┐│
│  │         Reconciler (协调器) ⭐          ││
│  │  • beginWork - 向下遍历                 ││
│  │  • completeWork - 向上回溯              ││
│  │  • reconcileChildFibers - 子节点协调   ││
│  └─────────────────────────────────────────┘│
│    ↓ 生成 Effect List                       │
│  ┌─────────────────────────────────────────┐│
│  │         Renderer (渲染器)               ││
│  │  • commitMutationEffects               ││
│  │  • DOM/原生平台操作                    ││
│  └─────────────────────────────────────────┘│
└─────────────────────────────────────────────┘

⏱️ 核心三阶段

1. Render Phase(渲染阶段) - 纯计算,可中断

2. Pre-commit Phase(预提交) - 读取 DOM 状态

3. Commit Phase(提交阶段) - 真实 DOM 操作,不可中断

阶段 可中断 核心函数 产出
Render ✅ 是 beginWork/completeWork 新的 Fiber 树 + Effect List
Pre-commit ❌ 否 commitBeforeMutationEffects 读取 DOM 快照
Commit ❌ 否 commitMutationEffects 真实 DOM 更新

🔄 Render 阶段详解

Render 阶段是协调的核心,通过深度优先遍历 Fiber 树来计算差异。

// Render 阶段核心循环
function workLoopConcurrent() {
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
}

function performUnitOfWork(unitOfWork: Fiber): void {
  const current = unitOfWork.alternate;
  // 1. beginWork - 处理当前节点
  let next = beginWork(current, unitOfWork, renderLanes);
  
  if (next === null) {
    // 2. completeWork - 没有子节点,开始回溯
    completeUnitOfWork(unitOfWork);
  } else {
    workInProgress = next; // 继续处理子节点
  }
}

📤 Commit 阶段详解

Commit 阶段是不可中断的同步操作,将计算结果应用到真实 DOM。

// Commit 阶段三个子阶段
function commitRoot(root: FiberRoot, recoverableErrors: ...) {
  // 1. Before Mutation (读取 DOM 状态)
  commitBeforeMutationEffects(root, finishedWork);
  
  // 2. Mutation (DOM 操作)
  commitMutationEffects(root, finishedWork);
  
  // 3. Layout (布局后同步执行)
  commitLayoutEffects(root, finishedWork);
  
  // 触发 passive effects (useEffect)
  scheduleCallback(NormalPriority, () => {
    flushPassiveEffects();
  });
}

📊 核心类概览

类/接口 文件 职责
Fiber ReactFiber.js 虚拟 DOM 节点
FiberRoot ReactFiberRoot.js 根容器状态
Lane ReactFiberLane.js 优先级模型
Flags ReactFiberFlags.js 副作用标记
WorkTag ReactWorkTags.js 组件类型标识

🔗 FiberNode 结构

// ReactFiber.js - Fiber 节点构造函数
function FiberNode(
  tag: WorkTag,          // 组件类型
  pendingProps: mixed,   // 待处理 props
  key: null | string,    // React key
  mode: TypeOfMode,      // 渲染模式
) {
  // Instance 字段
  this.tag = tag;
  this.key = key;
  this.elementType = null;
  this.type = null;
  this.stateNode = null;  // 对应的真实 DOM/组件实例

  // Fiber 树结构(链表)
  this.return = null;     // 父节点
  this.child = null;      // 第一个子节点
  this.sibling = null;    // 下一个兄弟节点
  this.index = 0;         // 在父节点中的索引

  // ... 更多字段
}

📋 FiberNode 字段详解

状态字段

  • pendingProps - 新 props
  • memoizedProps - 上次 props
  • updateQueue - 更新队列
  • memoizedState - Hooks 链表
  • dependencies - 依赖上下文

副作用字段

  • flags - 副作用标记
  • subtreeFlags - 子树标记
  • deletions - 待删除子节点
  • lanes - 优先级
  • alternate - 双缓冲指针
// 双缓冲:current 和 workInProgress 互相指向
let workInProgress = current.alternate;
workInProgress.alternate = current;

🌳 FiberRoot 结构

// ReactFiberRoot.js - 根容器
type FiberRoot = {
  tag: RootTag,              // LegacyRoot | ConcurrentRoot
  containerInfo: Container,   // DOM 容器
  pendingChildren: any,       // 子容器
  current: Fiber,             // 当前的 Fiber 树
  
  // 工作队列
  finishedWork: Fiber | null, // 已完成的 workInProgress
  finishedLanes: Lanes,       // 完成的优先级
  
  // 调度状态
  callbackNode: any,          // 调度任务
  callbackPriority: Lane,     // 调度优先级
  
  // 挂起的更新
  pendingLanes: Lanes,        // 待处理优先级
  suspendedLanes: Lanes,      // 挂起优先级
  pingedLanes: Lanes,         // 已唤醒优先级
};

🏷️ WorkTag 类型

// ReactWorkTags.js - 组件类型标识
export const FunctionComponent = 0;     // 函数组件
export const ClassComponent = 1;        // 类组件
export const HostRoot = 3;              // 根节点
export const HostPortal = 4;            // Portal
export const HostComponent = 5;         // 原生 DOM 元素
export const HostText = 6;              // 文本节点
export const Fragment = 7;              // Fragment
export const Mode = 8;                  // StrictMode 等
export const ContextProvider = 10;      // Context.Provider
export const ContextConsumer = 9;       // Context.Consumer
export const ForwardRef = 11;           // forwardRef
export const Profiler = 12;             // Profiler
export const SuspenseComponent = 13;    // Suspense
export const MemoComponent = 14;        // React.memo
export const SimpleMemoComponent = 15;  // 简单 memo
export const LazyComponent = 16;        // React.lazy

🚩 Flags 标记系统

// ReactFiberFlags.js - 副作用标记(位掩码)
export const NoFlags = /*                      */ 0b0000000000000000;
export const PerformedWork = /*                */ 0b0000000000000001;
export const Placement = /*                    */ 0b0000000000000010; // 插入
export const Update = /*                       */ 0b0000000000000100; // 更新
export const ChildDeletion = /*                */ 0b0000000000001000; // 删除子节点
export const ContentReset = /*                 */ 0b0000000000010000; // 内容重置
export const Callback = /*                     */ 0b0000000000100000; // 回调
export const DidCapture = /*                   */ 0b0000000001000000; // 捕获错误
export const Ref = /*                          */ 0b0000000010000000; // Ref 更新
export const Snapshot = /*                     */ 0b0000000100000000; // 快照
export const Passive = /*                      */ 0b0000001000000000; // useEffect
export const Visibility = /*                   */ 0b0000010000000000; // 可见性

🛤️ Lane 模型

Lane 模型是 React 18 引入的优先级系统,用 31 位二进制表示不同的优先级级别。

// ReactFiberLane.js - 优先级模型
export const TotalLanes = 31;
export const NoLanes: Lanes = 0b0000000000000000000000000000000;
export const NoLane: Lane =   0b0000000000000000000000000000000;

// 同步优先级(最高)
export const SyncLane: Lane = 0b0000000000000000000000000000010;
// 连续输入(如 mousemove)
export const InputContinuousLane: Lane = 0b0000000000000000000000000001000;
// 默认优先级
export const DefaultLane: Lane = 0b0000000000000000000000000100000;
// 过渡优先级(startTransition)
const TransitionLanes: Lanes = 0b0000000001111111111111100000000;
// 空闲优先级(最低)
export const IdleLane: Lane = 0b0010000000000000000000000000000;

📊 Lane 优先级详解

Lane 优先级 使用场景
SyncLane 最高 同步渲染、用户输入
InputContinuousLane 连续输入(拖拽、滚动)
DefaultLane 普通更新
TransitionLane startTransition 包装的更新
IdleLane 最低 空闲时执行

核心原则:高优先级更新可以打断低优先级更新

⬇️ beginWork 函数

// ReactFiberBeginWork.js - 向下遍历处理节点
function beginWork(
  current: Fiber | null,    // 当前显示的 Fiber
  workInProgress: Fiber,    // 正在构建的 Fiber
  renderLanes: Lanes,       // 当前渲染优先级
): Fiber | null {
  
  // 检查是否可以复用(bailout)
  if (current !== null) {
    const oldProps = current.memoizedProps;
    const newProps = workInProgress.pendingProps;
    
    if (oldProps === newProps && !checkScheduledUpdateDidRender()) {
      // Props 未变化,且无更新 → 复用子树
      return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    }
  }
  
  // 根据 tag 分发到不同处理函数
  switch (workInProgress.tag) {
    case FunctionComponent: return updateFunctionComponent(...);
    case ClassComponent: return updateClassComponent(...);
    case HostComponent: return updateHostComponent(...);
    // ...
  }
}

🔄 beginWork 流程

beginWork 处理流程:
┌─────────────────────────────────────┐
│         进入 beginWork              │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  检查是否可以 bailout(复用)       │
│  • props 是否相同?                 │
│  • 是否有待处理的更新?             │
└─────────────────────────────────────┘
        ↓ 否                    ↓ 是
┌───────────────────┐    ┌──────────────┐
│ 根据 tag 执行     │    │ bailout 复用 │
│ 对应的 update 函数 │    │ 返回 null   │
└───────────────────┘    └──────────────┘
        ↓
┌─────────────────────────────────────┐
│ reconcileChildren(协调子节点)     │
│ • 单节点:reconcileSingleElement    │
│ • 数组:reconcileChildrenArray      │
└─────────────────────────────────────┘
        ↓
┌─────────────────────────────────────┐
│ 返回第一个子 Fiber(继续向下遍历)  │
└─────────────────────────────────────┘

⬆️ completeWork 函数

// ReactFiberCompleteWork.js - 向上回溯处理节点
function completeWork(
  current: Fiber | null,
  workInProgress: Fiber,
  renderLanes: Lanes,
): Fiber | null {
  
  const newProps = workInProgress.pendingProps;
  
  switch (workInProgress.tag) {
    case HostComponent: {
      // 原生 DOM 元素
      if (current !== null && workInProgress.stateNode != null) {
        // 更新场景:标记 Update flag
        updateHostComponent(current, workInProgress, type, newProps);
      } else {
        // 挂载场景:创建 DOM 实例
        const instance = createInstance(type, newProps, ...);
        workInProgress.stateNode = instance;
        appendAllChildren(instance, workInProgress);
      }
      break;
    }
    // ... 其他类型处理
  }
}

🔙 completeWork 流程

completeWork 处理流程:
┌─────────────────────────────────────┐
│         进入 completeWork           │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  根据 tag 执行对应的完成处理        │
│  • HostComponent: 创建/更新 DOM     │
│  • HostText: 创建文本节点           │
│  • ClassComponent: 处理生命周期     │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  冒泡副作用 flags 到父节点          │
│  workInProgress.return.flags |=     │
│    workInProgress.subtreeFlags      │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  返回兄弟节点或父节点               │
│  sibling || return                  │
└─────────────────────────────────────┘

✅ commitWork 函数

// ReactFiberCommitWork.js - 提交副作用
function commitRoot(
  root: FiberRoot,
  recoverableErrors: Array<mixed>,
  transientUpdates: Array<mixed> | null,
) {
  // 阶段 1: Before Mutation
  commitBeforeMutationEffects(root, finishedWork);
  // - getSnapshotBeforeUpdate
  // - schedule useEffect
  
  // 阶段 2: Mutation
  commitMutationEffects(root, finishedWork);
  // - 插入/更新/删除 DOM
  // - ref 更新
  
  // 阶段 3: Layout
  commitLayoutEffects(root, finishedWork);
  // - componentDidMount/Update
  // - useLayoutEffect
}

🔧 commitMutationEffects

// DOM 操作的核心函数
function commitMutationEffects(
  root: FiberRoot,
  finishedWork: Fiber,
) {
  // 遍历 Effect List
  commitMutationEffects_begin(finishedWork, root);
}

function commitMutationEffectsOnFiber(
  finishedWork: Fiber,
  root: FiberRoot,
) {
  const flags = finishedWork.flags;
  
  // 处理 Placement(插入)
  if (flags & Placement) {
    commitPlacement(finishedWork);
    finishedWork.flags &= ~Placement;
  }
  
  // 处理 Update(更新)
  if (flags & Update) {
    commitUpdate(finishedWork);
    finishedWork.flags &= ~Update;
  }
  
  // 处理 ChildDeletion(删除)
  if (flags & ChildDeletion) {
    const deletions = finishedWork.deletions;
    deletions.forEach(child => commitDeletion(child, root));
  }
}

🔄 reconcileChildFibers

// ReactChildFiber.js - 子节点协调的核心
function reconcileChildFibers(
  returnFiber: Fiber,
  currentFirstChild: Fiber | null,
  newChild: any,
  lanes: Lanes,
): Fiber | null {
  
  // 判断子节点类型
  if (typeof newChild === 'object' && newChild !== null) {
    switch (newChild.$$typeof) {
      case REACT_ELEMENT_TYPE:
        // 单个 React 元素
        return reconcileSingleElement(...);
      case REACT_PORTAL_TYPE:
        return reconcileSinglePortal(...);
    }
    
    if (isArray(newChild)) {
      // 数组子节点
      return reconcileChildrenArray(...);
    }
  }
  
  if (typeof newChild === 'string' || typeof newChild === 'number') {
    // 文本子节点
    return reconcileSingleTextNode(...);
  }
  
  // 其他情况返回 null
  return deleteRemainingChildren(returnFiber, currentFirstChild);
}

📊 子节点协调策略

子节点类型 处理函数 说明
单个元素 reconcileSingleElement 创建或复用单个子节点
文本节点 reconcileSingleTextNode 处理纯文本子节点
数组 reconcileChildrenArray Diff 算法的核心
Iterator reconcileChildrenIterator 处理可迭代对象

关键:React 的 Diff 算法只处理数组场景,遵循"同层级比较"原则

🌱 mountChildFibers

// 首次渲染时,current 为 null
function mountChildFibers(
  returnFiber: Fiber,
  newChild: any,
  lanes: Lanes,
): Fiber | null {
  // 没有旧 Fiber,直接创建新 Fiber
  // 不需要 Diff,所有节点都是新的
  
  if (typeof newChild === 'object' && newChild !== null) {
    switch (newChild.$$typeof) {
      case REACT_ELEMENT_TYPE:
        return createFiberFromElement(newChild, returnFiber.mode, lanes);
    }
    
    if (isArray(newChild)) {
      // 数组:依次创建,标记 Placement
      return createChildReconciler(false)(returnFiber, null, newChild, lanes);
    }
  }
}

// mountChildFibers 和 reconcileChildFibers 的区别:
// - mountChildFibers: currentFirstChild = null, 不标记 Placement
// - reconcileChildFibers: currentFirstChild 不为 null, 需要 Diff

⚖️ 协调算法对比

mountChildFibers

  • 首次渲染
  • current = null
  • 直接创建 Fiber
  • 不执行 Diff
  • 不标记 Placement

reconcileChildFibers

  • 更新渲染
  • current ≠ null
  • Diff 比较
  • 复用或创建
  • 标记副作用

Diff 三原则:

  1. 不同类型元素 → 重建整个子树
  2. 同类型 DOM 元素 → 更新属性
  3. 同类型组件元素 → 更新 props

🔄 WorkLoop 核心

// ReactFiberWorkLoop.js - 工作循环
function workLoopConcurrent() {
  // 可中断的工作循环
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
}

function workLoopSync() {
  // 同步工作循环(不可中断)
  while (workInProgress !== null) {
    performUnitOfWork(workInProgress);
  }
}

// shouldYield() 来自 Scheduler
// 检查当前帧是否还有剩余时间
function shouldYield(): boolean {
  return getCurrentTime() >= deadline;
}

⏱️ workLoopConcurrent

// 并发模式下的工作循环
function workLoopConcurrent() {
  // 循环条件:
  // 1. 还有待处理的 Fiber
  // 2. 时间片未用完(shouldYield = false)
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
  
  // 循环结束后检查
  if (workInProgress !== null) {
    // 被中断,需要恢复
    root.callbackNode = scheduleCallback(
      workInProgressRootPriority,
      performConcurrentWorkOnRoot.bind(null, root)
    );
  } else {
    // 完成,进入 commit 阶段
    finishConcurrentRender(root, finishedWork);
  }
}

🔨 performUnitOfWork

// 处理单个 Fiber 单元
function performUnitOfWork(unitOfWork: Fiber): void {
  const current = unitOfWork.alternate;
  
  // 1. beginWork: 向下遍历
  let next = beginWork(current, unitOfWork, renderLanes);
  
  // 重置 pendingProps(已处理)
  unitOfWork.memoizedProps = unitOfWork.pendingProps;
  
  if (next === null) {
    // 没有子节点,开始回溯
    completeUnitOfWork(unitOfWork);
  } else {
    // 有子节点,继续向下
    workInProgress = next;
  }
}

// 深度优先遍历顺序:
// beginWork(A) → beginWork(B) → beginWork(C)
// → completeWork(C) → completeWork(B) → completeWork(A)

📅 调度与优先级

React 使用 Scheduler 进行任务调度,基于 Lane 模型管理优先级。

// 调度更新
function scheduleUpdateOnFiber(root: FiberRoot, fiber: Fiber, lane: Lane) {
  // 1. 标记更新优先级
  markRootUpdated(root, lane);
  
  // 2. 确保已调度
  ensureRootIsScheduled(root);
}

function ensureRootIsScheduled(root: FiberRoot) {
  // 获取最高优先级的 Lane
  const nextLanes = getNextLanes(root);
  
  // 如果已有调度且优先级相同,复用
  if (existingCallbackPriority === nextLanes) {
    return;
  }
  
  // 调度新任务
  const newCallbackNode = scheduleCallback(
    priorityLevel,
    performConcurrentWorkOnRoot.bind(null, root)
  );
  root.callbackNode = newCallbackNode;
}

🎭 双缓冲机制

React 使用双缓冲(Double Buffering)来维护两棵 Fiber 树:

// 双缓冲示意图
                    FiberRoot
                        │
                        ↓ current
                 ┌─────────────┐
                 │  current 树  │ ← 当前显示的树
                 │   (Fiber)   │
                 └─────────────┘
                        ↑
                    alternate
                        │
                 ┌─────────────┐
                 │ workInProgress│ ← 正在构建的树
                 │    (Fiber)   │
                 └─────────────┘

// Render 阶段完成后
root.current = finishedWork; // 切换指针

// 双缓冲的好处:
// 1. 避免在构建过程中显示不完整的 UI
// 2. 可以复用上一次的 Fiber 节点
// 3. 支持中断和恢复

📝 Effect List 构建

// completeWork 中冒泡副作用
function completeUnitOfWork(unitOfWork: Fiber): void {
  let completedWork = unitOfWork;
  
  do {
    // 1. 完成当前节点
    completeWork(current, completedWork, renderLanes);
    
    // 2. 收集子节点的副作用
    const subtreeFlags = completedWork.subtreeFlags;
    const flags = completedWork.flags;
    
    // 3. 冒泡到父节点
    const returnFiber = completedWork.return;
    if (returnFiber !== null) {
      returnFiber.subtreeFlags |= subtreeFlags | flags;
      returnFiber.flags |= subtreeFlags;
    }
    
    // 4. 处理兄弟节点
    const siblingFiber = completedWork.sibling;
    if (siblingFiber !== null) {
      workInProgress = siblingFiber;
      return; // 处理兄弟
    }
    
    completedWork = returnFiber; // 回溯到父节点
  } while (completedWork !== null);
}

🎨 设计模式

React Reconciler 中应用了多种经典设计模式:

结构型模式

  • 链表模式 - Fiber 树结构
  • 组合模式 - 组件树
  • 代理模式 - refs

行为型模式

  • 策略模式 - 不同组件类型
  • 观察者模式 - Context
  • 状态模式 - Hooks

🔗 链表模式

// Fiber 树使用链表结构
class Fiber {
  return: Fiber | null;   // 父节点指针
  child: Fiber | null;    // 第一个子节点
  sibling: Fiber | null;  // 下一个兄弟节点
}

// 遍历示例
function traverseFiber(fiber: Fiber) {
  // 处理当前节点
  visit(fiber);
  
  // 递归遍历子节点
  let child = fiber.child;
  while (child !== null) {
    traverseFiber(child);
    child = child.sibling; // 通过 sibling 访问下一个子节点
  }
}

// 链表的好处:
// 1. 内存效率高(不需要数组)
// 2. 插入/删除 O(1)
// 3. 支持可中断遍历

🔢 位掩码模式

// Flags 使用位掩码
export const NoFlags = 0;
export const Placement = 0b00000010;
export const Update = 0b00000100;
export const ChildDeletion = 0b00001000;

// 设置标记
fiber.flags |= Placement | Update;

// 检查标记
if (fiber.flags & Placement) {
  // 需要插入
}

// 清除标记
fiber.flags &= ~Placement;

// 位掩码的好处:
// 1. 内存效率高(一个数字存储多个标记)
// 2. 操作速度快(位运算)
// 3. 支持组合检查

// Lane 模型也使用位掩码
const allSyncLanes = SyncLane | InputContinuousLane | DefaultLane;

⏰ 调度器模式

// Scheduler 是独立的调度器包
import { scheduleCallback, shouldYield } from './Scheduler';

// 任务队列(最小堆)
const taskQueue: Array<Task> = [];

// 调度任务
function scheduleCallback(priority, callback) {
  const task = {
    callback,
    priority,
    expirationTime: currentTime + timeout,
  };
  push(taskQueue, task); // 放入最小堆
  requestHostCallback(); // 请求执行
}

// 工作循环
function workLoop() {
  while (taskQueue.length > 0) {
    if (shouldYield()) break; // 时间片用完
    const task = peek(taskQueue);
    task.callback();
    pop(taskQueue);
  }
}

📐 架构 UML

┌───────────────┐       ┌───────────────┐
│  FiberRoot    │       │    Fiber      │
├───────────────┤       ├───────────────┤
│ current       │───┐   │ tag           │
│ containerInfo │   │   │ key           │
│ pendingLanes  │   │   │ return        │────┐
│ callbackNode  │   │   │ child         │────┼──┐
└───────────────┘   │   │ sibling       │←───┘  │
                    │   │ alternate     │←──────┼──┐
                    │   │ flags         │       │  │
                    │   │ lanes         │       │  │
                    │   └───────────────┘       │  │
                    │                           │  │
                    └───────────────────────────┘  │
                         │                          │
                         └──────────────────────────┘
                    (双缓冲:current ↔ workInProgress)

🔄 协调流程图

触发更新 (setState/dispatch)
         │
         ↓
┌─────────────────────┐
│ scheduleUpdateOnFiber│
│ 标记 Lane,调度任务  │
└─────────────────────┘
         │
         ↓
┌─────────────────────┐
│ ensureRootIsScheduled│
│ 根据优先级调度      │
└─────────────────────┘
         │
         ↓
┌─────────────────────┐
│ performConcurrentWork│
│ Render 阶段开始     │
└─────────────────────┘
         │
    ┌────┴────┐
    ↓         ↓
beginWork  completeWork
(向下遍历)  (向上回溯)
    │         │
    └────┬────┘
         ↓
┌─────────────────────┐
│   commitRoot        │
│   Commit 阶段       │
└─────────────────────┘

🌳 Begin/Complete 流程

     A (beginWork)
    / \
   B   C (beginWork)
  /     \
 D       E (beginWork)
 │       │
(complete) (complete)
 │       │
 D       E ← completeWork
 │       
(complete)
 │
 B ← completeWork
 │
     C ← completeWork
     │
     A ← completeWork

// 遍历顺序:A→B→D→D完成→B完成→C→E→E完成→C完成→A完成
// 典型的深度优先遍历(DFS)

📤 Commit 流程图

commitRoot
    │
    ├─→ commitBeforeMutationEffects
    │       │
    │       ├─→ getSnapshotBeforeUpdate (Class)
    │       └─→ scheduleCallback (useEffect)
    │
    ├─→ commitMutationEffects
    │       │
    │       ├─→ commitPlacement (插入)
    │       ├─→ commitUpdate (更新)
    │       └─→ commitDeletion (删除)
    │
    └─→ commitLayoutEffects
            │
            ├─→ componentDidMount/Update (Class)
            ├─→ useLayoutEffect
            └─→ ref.callback

    然后异步执行 → flushPassiveEffects (useEffect)

🛤️ Lane 调度流程

setState 调用
     │
     ↓
┌────────────────────┐
│ requestUpdateLane  │ ← 根据事件类型获取 Lane
│ - Discrete: Sync   │
│ - Continuous: Input│
│ - Default: Default │
│ - Transition: Trans│
└────────────────────┘
     │
     ↓
┌────────────────────┐
│ enqueueUpdate      │ ← 将 update 加入队列
│ fiber.updateQueue  │
└────────────────────┘
     │
     ↓
┌────────────────────┐
│ scheduleUpdateOnFiber│ ← 标记 root.pendingLanes
│ markRootUpdated    │
└────────────────────┘
     │
     ↓
┌────────────────────┐
│ getNextLanes       │ ← 获取最高优先级
│ 调度对应优先级任务 │
└────────────────────┘

⚡ 性能优化策略

调度优化

  • 时间切片
  • 优先级抢占
  • 批量更新
  • 任务合并

渲染优化

  • bailout 复用
  • memo/useMemo
  • 虚拟列表
  • 懒加载

核心原则:减少不必要的重新渲染

⏱️ 时间切片

// Scheduler 的时间切片实现
const frameInterval = 5; // 5ms 时间片

function shouldYield(): boolean {
  const currentTime = getCurrentTime();
  const deadline = startTime + frameInterval;
  return currentTime >= deadline;
}

// React 中的使用
function workLoopConcurrent() {
  while (workInProgress !== null) {
    if (shouldYield()) {
      // 时间片用完,保存状态并退出
      root.callbackNode = scheduleCallback(
        priority,
        performConcurrentWorkOnRoot.bind(null, root)
      );
      return;
    }
    performUnitOfWork(workInProgress);
  }
}

// 好处:保持 UI 响应,不阻塞用户交互

📦 批量更新

// 自动批量更新(React 18)
function handleClick() {
  // 这些更新会被批量处理
  setCount(c => c + 1);
  setFlag(f => !f);
  // 只触发一次重新渲染
}

// 原理:共享同一个 Lane
function batchedUpdates(fn) {
  const prevExecutionContext = executionContext;
  executionContext |= BatchedContext;
  try {
    return fn();
  } finally {
    executionContext = prevExecutionContext;
    // 离开批量上下文时才调度
    if (executionContext === NoContext) {
      flushSyncCallbacks();
    }
  }
}

🚀 bailout 优化

// beginWork 中的 bailout 检查
function beginWork(current, workInProgress, renderLanes) {
  // 条件 1: current 存在(非首次渲染)
  // 条件 2: props 相同
  // 条件 3: 没有待处理的更新
  if (current !== null) {
    const oldProps = current.memoizedProps;
    const newProps = workInProgress.pendingProps;
    
    if (oldProps === newProps && 
        !checkHasForceUpdateAfterProcessing()) {
      // 复用整个子树
      return bailoutOnAlreadyFinishedWork(
        current, workInProgress, renderLanes
      );
    }
  }
  // ... 正常处理
}

// React.memo 的作用就是阻止 props 变化时的重渲染
// 使得 bailout 条件更容易满足

✅ 最佳实践

组件设计

  • 保持组件粒度适中
  • 合理使用 memo/useMemo
  • 避免不必要的 state
  • 使用 key 帮助 Diff

状态管理

  • 状态下沉到需要的组件
  • 使用 Context 谨慎
  • 考虑状态管理库
  • startTransition 标记低优先级

❌ 反模式

避免这些常见错误:

// ❌ 在渲染中产生副作用
function Component() {
  document.title = 'Bad'; // 副作用!
  return <div>...</div>;
}

// ❌ 过度使用 memo
const MemoChild = memo(Child); // 不总是需要

// ❌ 不稳定的 key
{items.map(item => (
  <Item key={Math.random()} /> // 每次都重建
))}

// ❌ 在 useEffect 中直接修改 state
useEffect(() => {
  setState(derived); // 可能导致循环
}, [dependency]);

// ❌ 同步阻塞操作
function handleClick() {
  heavyComputation(); // 阻塞渲染
}

🔍 调试技巧

// React DevTools Profiler
// 查看 Flamegraph 和 Ranked 视图

// 使用 React 内置的日志
// 在 React 源码中设置断点

// 关键断点位置:
// - beginWork (ReactFiberBeginWork.js)
// - completeWork (ReactFiberCompleteWork.js)
// - commitMutationEffects (ReactFiberCommitWork.js)
// - reconcileChildFibers (ReactChildFiber.js)

// 使用 React 的 __DEV__ 标志
if (__DEV__) {
  console.log('Current fiber:', current);
  console.log('Work in progress:', workInProgress);
  console.log('Flags:', flags);
}

// 查看调度状态
// Scheduler.unstable_getCurrentPriorityLevel()

⚖️ 与 Vue 对比

特性 React Vue
响应式系统 不可变 + Diff Mutable + Proxy
更新粒度 组件级 依赖追踪到具体属性
调度 基于 Lane 优先级 基于 job queue
虚拟 DOM Fiber 树 VNode 树
时间切片 支持(并发模式) 有限支持

🔮 未来发展趋势

React 19+

  • Compiler 自动优化
  • use() Hook
  • Server Components
  • 更好的并发特性

架构演进

  • 更细粒度的调度
  • 更好的 SSR 支持
  • 原生并发原语
  • 性能监控增强

📚 总结

核心要点回顾:

  • 协调过程:beginWork → completeWork → commitWork
  • Fiber 结构:链表树 + 双缓冲 + 位掩码标记
  • Lane 模型:31 位优先级系统,支持抢占式调度
  • 时间切片:可中断渲染,保持 UI 响应
  • Diff 算法:同层级比较 + key 匹配

关键文件:ReactFiberWorkLoop.js, ReactFiberBeginWork.js, ReactChildFiber.js, ReactFiberLane.js

📖 参考资源

官方文档

  • React 官方文档
  • React GitHub 仓库
  • React RFCs

深度文章

  • Inside Fiber
  • Lane 模型详解
  • 并发模式原理

🔗 源码地址:github.com/facebook/react

📍 核心路径:packages/react-reconciler/src/