此阶段处理的工作

  • 处理与focus和blur事件

image.png

  • 如果effect Tag包含Snapshot,即ClassComponent对应的getSnapshotBeforeUpdate,处理commitBeforeMutationEffectsOnFiber。

image.png

  • 如果有effectTag,effectTag包含passive时,即FunctionComponent中对对应的useEffect的effect tag,需要调度flushPassiveEffects()

image.png

commitBeforeMutationEffectsOnFiber

如果effect Tag包含Snapshot,进入commitBeforeMutationEffectsOnFiber。如果是ClassComponent,就会 var instance = finishedWork.stateNode,获得component的实例,调用实例上的getSnapshotBeforeUpdate生命周期
因此getSnapshotBeforeUpdate,是在before mutation上调用,此时还没有页面可见的更新。

  1. function commitBeforeMutationEffectsOnFiber(finishedWork) {
  2. var current = finishedWork.alternate;
  3. var flags = finishedWork.flags;
  4. if ((flags & Snapshot) !== NoFlags) {
  5. setCurrentFiber(finishedWork);
  6. switch (finishedWork.tag) {
  7. case FunctionComponent:
  8. case ForwardRef:
  9. case SimpleMemoComponent:
  10. {
  11. break;
  12. }
  13. //如果是ClassComponent
  14. case ClassComponent:
  15. {
  16. if (current !== null) {
  17. var prevProps = current.memoizedProps;
  18. var prevState = current.memoizedState;
  19. var instance = finishedWork.stateNode;
  20. ....
  21. var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState);
  22. {
  23. var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate;
  24. if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) {
  25. didWarnSet.add(finishedWork.type);
  26. error('%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + 'must be returned. You have returned undefined.', getComponentNameFromFiber(finishedWork));
  27. }
  28. }
  29. instance.__reactInternalSnapshotBeforeUpdate = snapshot;
  30. }
  31. break;
  32. }
  33. case HostRoot:
  34. {
  35. {
  36. var root = finishedWork.stateNode;
  37. clearContainer(root.containerInfo);
  38. }
  39. break;
  40. }
  41. case HostComponent:
  42. case HostText:
  43. case HostPortal:
  44. case IncompleteClassComponent:
  45. // Nothing to do for these component types
  46. break;
  47. default:
  48. {
  49. 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.');
  50. }
  51. }
  52. resetCurrentFiber();
  53. }
  54. }

flushPassiveEffects

如果effectTag包含passive,此时并没有直接执行flushPassiveEffects。flushPassiveEffects会执行useEffect的回调函数。
为什么逻辑中没有直接执行flushPassiveEffects,而是作为scheduleCallback的回调函数?
scheduleCallback()会以一个优先级,来异步执行一个回调函数。如果一个FunctionComponent存在一个useEffect,并且他的useEffect的回调函数需要被触发的情况下,那么这个useEffect的回调会在before mutation阶段,先被NormalSchedulePriority的优先级调度。
而整个commit阶段是同步执行的,所以useEffect回调函数的执行,是在commit阶段完成以后,再异步执行的。
image.png