erp网站建设方案,flash 网站开发教程,最新足球新闻头条,外贸必看网站commitBeforeMutationLifecycles 1 #xff09;概述
在 react commit阶段的 commitRoot 第一个while循环中调用了 commitBeforeMutationLifeCycles现在来看下#xff0c;里面发生了什么
2 #xff09;源码
回到 commit 阶段的第一个循环中#xff0c;在 commitRoot 函数…commitBeforeMutationLifecycles 1 概述
在 react commit阶段的 commitRoot 第一个while循环中调用了 commitBeforeMutationLifeCycles现在来看下里面发生了什么
2 源码
回到 commit 阶段的第一个循环中在 commitRoot 函数里 定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L647
看这里
// Invoke instances of getSnapshotBeforeUpdate before mutation.
nextEffect firstEffect;
startCommitSnapshotEffectsTimer();// 接下去就进入了三个循环
// 第一个循环主要是 commitBeforeMutationLifecycles这个方法它其实很简单它是这三个循环当中最简单的一个方法
// 它唯一的作用就是调用 ClassComponent 上面可能会存在的 getSnapshotBeforeUpdate 这么一个生命周期方法
while (nextEffect ! null) {let didError false;let error;if (__DEV__) {invokeGuardedCallback(null, commitBeforeMutationLifecycles, null);if (hasCaughtError()) {didError true;error clearCaughtError();}} else {try {commitBeforeMutationLifecycles();} catch (e) {didError true;error e;}}if (didError) {invariant(nextEffect ! null,Should have next effect. This error is likely caused by a bug in React. Please file an issue.,);captureCommitPhaseError(nextEffect, error);// Clean-upif (nextEffect ! null) {nextEffect nextEffect.nextEffect;}}
}在开始循环之前都会用到一个全局变量叫做 nextEffect当然它一开始是 firstEffect 是在 RootFiber 上面它的 firstEffect 到 lastEffect 这个链表上面的第一个effect也就是第一个需要我们commit的fiber对象 需要注意一点这边有一个很奇怪的代码就是我们这个 commitBeforeMutationLifecycles 方法 可以看到 import { commitBeforeMutationLifeCycles } from ./ReactFiberCommitWork但是又在本文件中定义了一个同名的方法// 这个是核心
function commitBeforeMutationLifecycles() {while (nextEffect ! null) {if (__DEV__) {ReactCurrentFiber.setCurrentFiber(nextEffect);}const effectTag nextEffect.effectTag;if (effectTag Snapshot) {recordEffect();const current nextEffect.alternate;commitBeforeMutationLifeCycles(current, nextEffect); // 这个函数不是上层的自己而是 import 进来的}nextEffect nextEffect.nextEffect;}if (__DEV__) {ReactCurrentFiber.resetCurrentFiber();}
}这个操作会有点奇怪因为正常来讲import 进来的内容它是一个常量它不应该是能够直接被修改注意在 commitRoot 里调用的 commitBeforeMutationLifeCycles 是文件内的这个方法而文件内的这个方法调用的 commitBeforeMutationLifeCycles 是 import 进来的 它来自于 packages/react-reconciler/src/ReactFiberCommitWork.js#L215 它通过一个while循环循环的是我们的 effect链 在这个循环的后面可以看到 nextEffect nextEffect.nextEffect; 这就是说一个一个往下这么去循环对 有 Snapshot 这个 SideEffect 的节点执行了下面的方法
再次定位到 packages/react-reconciler/src/ReactFiberCommitWork.js#L215
进入 commitBeforeMutationLifeCycles 这个就是上面定义的同名函数里面调用的方法
function commitBeforeMutationLifeCycles(current: Fiber | null,finishedWork: Fiber,
): void {switch (finishedWork.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {commitHookEffectList(UnmountSnapshot, NoHookEffect, finishedWork);return;}case ClassComponent: {if (finishedWork.effectTag Snapshot) {if (current ! null) {const prevProps current.memoizedProps;const prevState current.memoizedState;startPhaseTimer(finishedWork, getSnapshotBeforeUpdate);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__) {if (finishedWork.type finishedWork.elementType) {warning(instance.props finishedWork.memoizedProps,Expected instance props to match memoized props before getSnapshotBeforeUpdate. This is likely due to a bug in React. Please file an issue.,);warning(instance.state finishedWork.memoizedState,Expected instance state to match memoized state before getSnapshotBeforeUpdate. This is likely due to a bug in React. Please file an issue.,);}}const snapshot instance.getSnapshotBeforeUpdate(finishedWork.elementType finishedWork.type? prevProps: resolveDefaultProps(finishedWork.type, prevProps),prevState,);if (__DEV__) {const didWarnSet ((didWarnAboutUndefinedSnapshotBeforeUpdate: any): Setmixed,);if (snapshot undefined !didWarnSet.has(finishedWork.type)) {didWarnSet.add(finishedWork.type);warningWithoutStack(false,%s.getSnapshotBeforeUpdate(): A snapshot value (or null) must be returned. You have returned undefined.,getComponentName(finishedWork.type),);}}instance.__reactInternalSnapshotBeforeUpdate snapshot;stopPhaseTimer();}}return;}case HostRoot:case HostComponent:case HostText:case HostPortal:case IncompleteClassComponent:// Nothing to do for these component typesreturn;default: {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.,);}}
}它传入的 current 是 workInProgress 对象也就是fiber对象然后传入的 nextEfect 是 finishedWork 对象通过 instance.getSnapshotBeforeUpdate 传入两个 props 来获取 snapshot 快照对象之后将 snapshot 挂载到 instance.__reactInternalSnapshotBeforeUpdate对于其他类型的组件它都没有任何的处理只处理了 ClassComponent因为对这种情况来说只有 ClassComponent 有这个 SideEffect并且会有 getSnapshotBeforeUpdate 这个生命周期方法的