Skip to content
目录

commitBeforeMutationLifecycles

commitRoot的第一个循环做的事情, 主要是针对class组件的getSnapshotBeforeUpdate钩子的调用

typescript
function commitBeforeMutationLifecycles() {
  while (nextEffect !== null) {
    const effectTag = nextEffect.effectTag;
    // 如果有Snapshot的tag,就执行commitBeforeMutationLifeCycles
    // 对于class组件,执行getSnapshotBeforeUpdate
    if (effectTag & Snapshot) {
      const current = nextEffect.alternate;
      commitBeforeMutationLifeCycles(current, nextEffect);
    }

    nextEffect = nextEffect.nextEffect;
  }
}

Snapshot Tag的标记

Snapshot具体是在什么时候标记的呢?其实就是在renderRoot阶段,针对class组件的更新,调用的了 updateClassInstance方法,其中:

typescript
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
  if (
    oldProps !== current.memoizedProps ||
    oldState !== current.memoizedState
  ) {
    workInProgress.effectTag |= Snapshot;
  }
}

只要是定义了getSnapshotBeforeUpdate方法,就会增加Snapshot的tag,然后commit阶段调用

commitBeforeMutationLifeCycles

commitBeforeMutationLifeCycles具体做的就是调用class组件的方法了

typescript
function commitBeforeMutationLifeCycles(
  current: Fiber | null,
  finishedWork: Fiber,
): void {
  switch (finishedWork.tag) {
    case SimpleMemoComponent: {
      // 传入的tag UnmountSnapshot NoHookEffect
      // useEffect 和 useLayoutEffect 没有使用这两个tag
      // 所以在这个阶段, useEffect 和 useLayoutEffect 都不会被调用
      // 实测了一下 SimpleMemoComponent 就是使用React.memo包裹的组件
      // 目前好像走不到这个逻辑
      commitHookEffectList(UnmountSnapshot, NoHookEffect, finishedWork);
      return;
    }
    case ClassComponent: {
      if (finishedWork.effectTag & Snapshot) {
        if (current !== null) {
          const prevProps = current.memoizedProps;
          const prevState = current.memoizedState;
          const instance = finishedWork.stateNode;
          const snapshot = instance.getSnapshotBeforeUpdate(
            finishedWork.elementType === finishedWork.type
              ? prevProps
              : resolveDefaultProps(finishedWork.type, prevProps),
            prevState,
          );
          // 将getSnapshotBeforeUpdate的返回值存储在当前实例上面,
          // 在componentDidUpdate的时候取出来,作为第三个参数传入
          instance.__reactInternalSnapshotBeforeUpdate = snapshot;
          stopPhaseTimer();
        }
      }
      return;
    }
  }
}

说明

typescript
instance.__reactInternalSnapshotBeforeUpdate = snapshot;

这里将getSnapshotBeforeUpdate的返回值存储在当前实例上面,在componentDidUpdate的时候取出来,作为第三个参数传入

注意

commitBeforeMutationLifecycles和commitBeforeMutationLifeCycles是两个方法,Cycles的大小写不一样

备案号: 浙ICP备2023000081号