此阶段处理的工作
- 处理与focus和blur事件
- 如果effect Tag包含Snapshot,即ClassComponent对应的getSnapshotBeforeUpdate,处理commitBeforeMutationEffectsOnFiber。
- 如果有effectTag,effectTag包含passive时,即FunctionComponent中对对应的useEffect的effect tag,需要调度flushPassiveEffects()
commitBeforeMutationEffectsOnFiber
如果effect Tag包含Snapshot,进入commitBeforeMutationEffectsOnFiber。如果是ClassComponent,就会 var instance = finishedWork.stateNode,获得component的实例,调用实例上的getSnapshotBeforeUpdate生命周期。
因此getSnapshotBeforeUpdate,是在before mutation上调用,此时还没有页面可见的更新。
function commitBeforeMutationEffectsOnFiber(finishedWork) {
var current = finishedWork.alternate;
var flags = finishedWork.flags;
if ((flags & Snapshot) !== NoFlags) {
setCurrentFiber(finishedWork);
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent:
{
break;
}
//如果是ClassComponent
case ClassComponent:
{
if (current !== null) {
var prevProps = current.memoizedProps;
var prevState = current.memoizedState;
var instance = finishedWork.stateNode;
....
var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState);
{
var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate;
if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) {
didWarnSet.add(finishedWork.type);
error('%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + 'must be returned. You have returned undefined.', getComponentNameFromFiber(finishedWork));
}
}
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
break;
}
case HostRoot:
{
{
var root = finishedWork.stateNode;
clearContainer(root.containerInfo);
}
break;
}
case HostComponent:
case HostText:
case HostPortal:
case IncompleteClassComponent:
// Nothing to do for these component types
break;
default:
{
throw new Error('This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.');
}
}
resetCurrentFiber();
}
}
flushPassiveEffects
如果effectTag包含passive,此时并没有直接执行flushPassiveEffects。flushPassiveEffects会执行useEffect的回调函数。
为什么逻辑中没有直接执行flushPassiveEffects,而是作为scheduleCallback的回调函数?
scheduleCallback()会以一个优先级,来异步执行一个回调函数。如果一个FunctionComponent存在一个useEffect,并且他的useEffect的回调函数需要被触发的情况下,那么这个useEffect的回调会在before mutation阶段,先被NormalSchedulePriority的优先级调度。
而整个commit阶段是同步执行的,所以useEffect回调函数的执行,是在commit阶段完成以后,再异步执行的。