Appearance
commitBeforeMutationEffects
Commit阶段对于副作用的第一次遍历处理过程。
在这个阶段每一个FiberNode对应的DOM元素已经生成,但是没有插入到浏览器中(保存在内存中),
其主要作用如下:
- 组件的Blur事件
- 处理 Class组件 getSnapshotBeforeUpdate() 生命周期方法副作用
- 处理 useEffect 类型的 effect 副作用
处理 Class组件 getSnapshotBeforeUpdate() 生命周期方法副作用
这个过程具体的方法为 commitBeforeMutationLifeCycles(current, finishedWork )
js
/**
* Commit阶段 在DOM插入浏览器之前 触发生命周期函数
* - 回调 Class组件 getSnapshotBeforeUpdate() 生命周期方法副作用
* - HostRoot 清除根节点的子元素 div#root 下的元素
* @param {*} current
* @param {*} finishedWork
* @returns
*/
function commitBeforeMutationLifeCycles(
current: Fiber | null,
finishedWork: Fiber,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent:
case Block: {
return;
}
case ClassComponent: {
if (finishedWork.flags & Snapshot) {
if (current !== null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
// 触发 getSnapshotBeforeUpdate(prevProps, prevState)
// prevProps 之前的props
// 之前的 state
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
}
return;
}
case HostRoot: {
if (supportsMutation) {
if (finishedWork.flags & Snapshot) {
const root = finishedWork.stateNode;
// 清空跟节点DOM元素div#root下的子元素
clearContainer(root.containerInfo);
}
}
return;
}
case HostComponent:
case HostText:
case HostPortal:
case IncompleteClassComponent:
// Nothing to do for these component types
return;
}
}
可以看到其核心就是调用class组件的getSnapshotBeforeUpdate生命周期方法
getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()
。
处理 useEffect 类型的 effect 副作用
这是官网对于useEffect的解释,具体功能放到useEffect讲解
我们这边主要说的是在这个过程中,会将useEffect类型的副作用放到任务队列中去
js
// 处理 useEffect 类型的 effect
// 主要是将其放到任务队列中去
if ((flags & Passive) !== NoFlags) {
// If there are passive effects, schedule a callback to flush at
// the earliest opportunity.
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
return null;
});
}
}