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的大小写不一样