🧑💻 前言
在上一篇文章里,我们从 scheduleUpdateOnFiber
出发,分析了 render 阶段的完整流程 :从 beginWork
递到 completeWork
归,最终构建 Fiber 树和 DOM。
那么,在这整个流程里,组件的 props 和 state 究竟是如何确定和存储的?
1. Props & State 在 Fiber 中的存储
先来看 Fiber 节点和 props/state 的关系:
js
type Fiber = {
pendingProps: any; // 新的 props
memoizedProps: any; // 已确认的 props
memoizedState: any; // 已确认的 state
updateQueue: any; // 更新队列
stateNode: any; // 类实例 or DOM 节点
}
要点:
-
props :从父组件传入,先放到
pendingProps
,在performUnitOfWork
结束时赋值给memoizedProps
。 -
state:来源不同:
- 类组件 →
constructor(this.state)
- 函数组件 →
useState
初始化 Hook 链表 - DOM 节点没有 state
- 类组件 →
2. Props 流程
来看 performUnitOfWork
的关键逻辑:
js
function performUnitOfWork(unitOfWork) {
const next = beginWork(unitOfWork.alternate, unitOfWork, renderLanes);
// 🔥 在这里 props 生效
unitOfWork.memoizedProps = unitOfWork.pendingProps;
return next;
}
- 每个 Fiber 在进入 beginWork 前,props 存在
pendingProps
。 - beginWork 执行完,
pendingProps
→memoizedProps
。 - 归阶段不再修改 props。
👉 所以:props 的确认时机在递阶段执行完毕时。
3. State 流程
3.1 类组件
js
function updateClassComponent(current, workInProgress, Component, nextProps) {
if (!workInProgress.stateNode) {
// 🔥 构造实例并初始化 state
const instance = new Component(nextProps);
workInProgress.stateNode = instance;
workInProgress.memoizedState = instance.state;
}
const nextChildren = workInProgress.stateNode.render();
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
}
特点:
new Component(props)
创建实例 → state 从constructor
里拿。fiber.memoizedState = instance.state
。- 每次更新时,
updateQueue
合并后的结果也会写到memoizedState
。
3.2 函数组件
js
function updateFunctionComponent(current, workInProgress, Component, nextProps) {
let nextChildren = renderWithHooks(current, workInProgress, Component, nextProps);
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
}
内部执行:
js
function mountState(initialState) {
const hook = mountWorkInProgressHook();
hook.memoizedState = initialState;
return [hook.memoizedState, dispatchSetState];
}
特点:
- 首次挂载时,
HooksDispatcherOnMount
生效。 useState(initial)
→ 创建 Hook 对象,挂到 Fiber.memoizedState 形成链表。- 后续更新时,Hook 链表会被复用。
3.3 DOM 节点
js
function updateHostComponent(current, workInProgress, renderLanes) {
const nextProps = workInProgress.pendingProps;
// HostComponent 没有 state
reconcileChildren(current, workInProgress, nextProps.children, renderLanes);
}
特点:
- 只有
props
,没有state
。 memoizedState
恒为null
。
4. Props & State 流程图
js
父组件传入 props → Fiber.pendingProps
↓
beginWork 执行完毕
↓
Fiber.memoizedProps = pendingProps // props 确认
↓
ClassComponent: memoizedState = instance.state
FunctionComponent: memoizedState = Hook 链表
HostComponent: 无 state
5. 小结对比
组件类型 | Props 确认位置 | State 初始化来源 | Fiber 存储点 |
---|---|---|---|
类组件 | performUnitOfWork |
constructor(this.state) |
memoizedProps & memoizedState |
函数组件 | performUnitOfWork |
useState(initial) Hook |
memoizedProps & Hook 链表 |
DOM 组件 | performUnitOfWork |
无 | memoizedProps ,无 state |
📌 总结
-
Props :统一流程,进入 beginWork 时在
pendingProps
,出 beginWork 后确认到memoizedProps
。 -
State:来源依组件类型不同:
- 类组件 → 构造函数初始化,存 Fiber.memoizedState
- 函数组件 → useState 初始化 Hook 链表,存 Fiber.memoizedState
- DOM 组件 → 无 state
-
最终落点 :无论 props 还是 state,都会落到 Fiber 节点上。
一句话总结:
👉 首次挂载时,props 在递阶段确认,state 按组件类型初始化,统一写入 Fiber,供后续 render & commit 使用。