React before mutation阶段

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.’,
);
}
新版生命周期。[1]

React before mutation阶段

总结
这节主要学习before mutation阶段函数调用流程

commitRootImpl是commit阶段主要函数,调用commitBeforeMutationEffects
commitBeforeMutationEffects主要功能是:执行commitBeforeMutationEffectOnFiber和通过flushPassiveEffects调度useEffect
commitBeforeMutationEffectOnFiber通过判断组件类型主要来执行类组件getSnapshotBeforeUpdate生命周期函数

React before mutation阶段

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至22018681@qq.com 举报,一经查实,本站将立刻删除。

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
森林服务号的头像森林服务号
上一篇 2022年4月11日 上午9:13
下一篇 2022年4月11日

相关推荐

发表回复

登录后才能评论