setState 更新流程:从 dispatchAction 到 Fiber 更新与 lane 调度
·
第一阶段已经完成了首轮 render + commit + passive effect 的闭环。接下来进入第二阶段:状态更新驱动的 Fiber 更新流程,也就是我们日常开发中调用 setState 或 useState、useReducer 后 React 如何处理状态更新的完整链路。本文严格基于 React 19 源码,解析更新是如何被调度、Fiber 如何复用、updateQueue 和 lanes 如何协作,以及最终如何触发 render 阶段。
一、dispatchAction:状态更新的入口
在函数组件中,当我们调用:
const [count, setCount] = useState(0)
setCount(prev => prev + 1)
setCount实际上是通过dispatchAction创建的函数。- 它保存了对当前 Fiber 的引用以及对应的 updateQueue:
dispatchSetState(fiber, queue, action)
关键操作:
- 创建一个
update对象:
const update = {
action, // setState 或 useReducer 的更新函数 / 值
lane, // 本次更新的优先级 lane
next: null
}
- 将 update 加入 Fiber 的
updateQueue:
- 如果队列为空,直接挂上
- 如果队列已存在,追加到循环链表中
- 调用调度函数:
scheduleUpdateOnFiber(fiber, lane, eventTime)
二、updateQueue:Fiber 上的状态队列
每个 Hook 对应一个 updateQueue(在 Fiber.memoizedState 中链表存储)。结构简化如下:
{
baseState, // 用于计算下一个状态的基础 state
firstUpdate, // 待处理更新链表头
lastUpdate, // 待处理更新链表尾
dispatch // setState 函数
}
- 当我们调用
setState时,更新会被加入firstUpdate / lastUpdate - Fiber 的
memoizedState链表对应 Hook 的状态 - 更新会在下一次 render 阶段计算新的状态
三、scheduleUpdateOnFiber:Fiber 调度入口
scheduleUpdateOnFiber(fiber, lane, eventTime) 是 React 19 更新调度的核心入口。
核心职责:
- 标记 Fiber 的 lane,表示这个 Fiber 有 pending 更新:
fiber.lanes |= lane
- 确保 FiberRoot 在 rootSchedule 中:
- React 会把 FiberRoot 加入链表
firstScheduledRoot / lastScheduledRoot - 用微任务保证根调度任务被执行
- 调用调度器:
- React 19 对应同步任务或并发任务,最终会调用:
performWorkOnRootViaSchedulerTask(root)
这一步触发新的 render 阶段。
四、lane:优先级模型
React 19 引入 lane 来控制更新优先级:
- 每个 update 对应一个 lane,例如:
SyncLane // 同步更新,立即执行
InputContinuousLane
DefaultLane
TransitionLane // 并发过渡更新
- 同一个 Fiber 可以同时有多个 lane,表示多次更新需要调和
- 调度器会根据 lane 决定:
render 阶段是否同步
是否可以被中断
- React 会在
ensureRootIsScheduled中根据 lane 调度微任务或 Scheduler callback
五、Fiber 复用与 workInProgress 创建
在 render 阶段,React 会为每个更新创建 workInProgress Fiber:
- 如果 current Fiber 存在,调用:
createWorkInProgress(current, pendingProps)
- 如果是初次渲染,直接创建新的 Fiber
workInProgress Fiber 会复用旧 Fiber 的:
- Hook 链表
- stateNode(DOM 或 class 实例)
更新阶段的 render 阶段,workInProgress Fiber 会计算新的 state,并生成新的子 Fiber 链表。
六、更新链路概览
- dispatchAction:setState 调用产生 update,并加入 updateQueue
- scheduleUpdateOnFiber:调度 Fiber,标记 lane,确保 root 调度
- Scheduler 调度:调用
performWorkOnRootViaSchedulerTask - render 阶段:
beginWork→ 执行函数组件 / HostComponent / HostTextrenderWithHooks→ 计算新的 Hook 状态reconcileChildren→ 生成新的子 Fiber treecompleteWork→ 向上归并,创建/准备 DOM
- commit 阶段:
- beforeMutation / mutation / layout
- passive effect 异步 flush
- Fiber 状态切换:
root.current = finishedWork
- 下一轮更新继续调度 Fiber,lane 优先级保证高优先级任务先执行
七、并发更新下的行为
在 concurrent render 模式下:
- render 阶段可以被中断,workInProgress 暂存
- Scheduler 可以中断低优先级更新,让高优先级更新先执行
- lane 模型保证不同优先级的 update 不会混乱
- commit 阶段仍然不可中断
八、结论
- dispatchAction 是状态更新的第一步,直接关联 Fiber 和 updateQueue
- updateQueue 保存 Hook 状态更新和 pending update
- scheduleUpdateOnFiber 将 Fiber 加入 root schedule,触发新的 render
- lane 决定更新优先级、可中断性和调度顺序
- workInProgress Fiber 复用 current Fiber,实现状态隔离和并发安全
- render → completeWork → commitRoot → passive effect 构成完整的更新链路
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)