commit 阶段分为三个局部
- before mutation 阶段
- mutation 阶段
- layout 阶段
次要都是在 commitRootImpl 函数内进行调用
commitRootImpl
这里只展现调用 before mutation 阶段的代码
if (firstEffect !== null) {
// 保留之前的优先级,以同步优先级执行,执行结束后复原之前优先级
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(SyncLanePriority);
// 将以后上下文标记为 CommitContext,作为 commit 阶段的标记
const prevExecutionContext = executionContext;
executionContext |= CommitContext;
const prevInteractions = pushInteractions(root);
// 在调用生命周期之前将此重置为 null
ReactCurrentOwner.current = null;
// The commit phase is broken into several sub-phases. We do a separate pass
// of the effect list for each phase: all mutation effects come before all
// layout effects, and so on.
// The first phase a "before mutation" phase. We use this phase to read the
// state of the host tree right before we mutate it. This is where
// getSnapshotBeforeUpdate is called.
focusedInstanceHandle = prepareForCommit(root.containerInfo);
shouldFireAfterActiveInstanceBlur = false;
nextEffect = firstEffect;
do {if (__DEV__) {
//.... 开发环境下调用
invokeGuardedCallback(null, commitBeforeMutationEffects, null);
if (hasCaughtError()) {invariant(nextEffect !== null, 'Should be working on an effect.');
const error = clearCaughtError();
captureCommitPhaseError(nextEffect, error);
nextEffect = nextEffect.nextEffect;
}
} else {
try {
// 调用 commitBeforeMutationEffects
commitBeforeMutationEffects();} catch (error) {invariant(nextEffect !== null, 'Should be working on an effect.');
captureCommitPhaseError(nextEffect, error);
nextEffect = nextEffect.nextEffect;
}
}
} while (nextEffect !== null);
//....
}
invokeGuardedCallback
开发环境下调用 commitBeforeMutationEffects 函数
function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
hasError = false;
caughtError = null;
invokeGuardedCallbackImpl$1.apply(reporter, arguments);
}
commitBeforeMutationEffects
调用 before mutation 次要函数
function commitBeforeMutationEffects() {while (nextEffect !== null) {
const current = nextEffect.alternate;
if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
// ...focus blur 相干
if ((nextEffect.effectTag & Deletion) !== NoEffect) {if (doesFiberContain(nextEffect, focusedInstanceHandle)) {
shouldFireAfterActiveInstanceBlur = true;
beforeActiveInstanceBlur();}
} else {
// TODO: Move this out of the hot path using a dedicated effect tag.
if (
nextEffect.tag === SuspenseComponent &&
isSuspenseBoundaryBeingHidden(current, nextEffect) &&
doesFiberContain(nextEffect, focusedInstanceHandle)
) {
shouldFireAfterActiveInstanceBlur = true;
beforeActiveInstanceBlur();}
}
}
const effectTag = nextEffect.effectTag;
if ((effectTag & Snapshot) !== NoEffect) {setCurrentDebugFiberInDEV(nextEffect);
// 调用 getSnapshotBeforeUpdate
commitBeforeMutationEffectOnFiber(current, nextEffect);
resetCurrentDebugFiberInDEV();}
// 调度 useEffect
if ((effectTag & Passive) !== NoEffect) {
// If there are passive effects, schedule a callback to flush at
// the earliest opportunity.
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {flushPassiveEffects();
return null;
});
}
}
nextEffect = nextEffect.nextEffect;
}
}
commitBeforeMutationEffectOnFiber
次要判断组件类型,如果是类组件就执行 getSnapshotBeforeUpdate 生命周期
function commitBeforeMutationLifeCycles(
current: Fiber | null,
finishedWork: Fiber,
): void {switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent:
case Block: {return;}
case ClassComponent: {if (finishedWork.effectTag & Snapshot) {if (current !== null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
// We could update instance props and state here,
// but instead we rely on them being set during last render.
// TODO: revisit this when we implement resuming.
if (__DEV__) {// ....}
// 调用 getSnapshotBeforeUpdate 生命周期
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
if (__DEV__) {// ....}
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
}
return;
}
case HostRoot: {if (supportsMutation) {if (finishedWork.effectTag & Snapshot) {
const root = finishedWork.stateNode;
clearContainer(root.containerInfo);
}
}
return;
}
case HostComponent:
case HostText:
case HostPortal:
case IncompleteClassComponent:
// Nothing to do for these component types
return;
}
invariant(
false,
'This unit of work tag should not have side-effects. This error is' +
'likely caused by a bug in React. Please file an issue.',
);
}
新版生命周期。
总结
这节次要学习 before mutation 阶段函数调用流程
- commitRootImpl 是 commit 阶段次要函数,调用 commitBeforeMutationEffects
- commitBeforeMutationEffects 次要性能是:执行 commitBeforeMutationEffectOnFiber 和通过 flushPassiveEffects 调度 useEffect
- commitBeforeMutationEffectOnFiber 通过判断组件类型次要来执行类组件 getSnapshotBeforeUpdate 生命周期函数