React|React before mutation阶段

commit阶段分为三个部分

  • before mutation阶段
  • mutation阶段
  • layout阶段
    主要都是在commitRootImpl函数内进行调用
commitRootImpl 【React|React before mutation阶段】这里只展示调用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.', ); }

新版生命周期。
React|React before mutation阶段
文章图片

总结 这节主要学习before mutation阶段函数调用流程
  • commitRootImpl是commit阶段主要函数,调用commitBeforeMutationEffects
  • commitBeforeMutationEffects主要功能是:执行commitBeforeMutationEffectOnFiber和通过flushPassiveEffects调度useEffect
  • commitBeforeMutationEffectOnFiber通过判断组件类型主要来执行类组件getSnapshotBeforeUpdate生命周期函数
React|React before mutation阶段
文章图片

    推荐阅读