在beginWork中生成当前fiber,点击查看详细代码。此处只看常用的IndeterminateComponent、FunctionComponent、ClassComponent、HostRoot、HostComponent、HostText。

  1. function beginWork(
  2. current: Fiber | null,
  3. workInProgress: Fiber,
  4. renderExpirationTime: ExpirationTime,
  5. ): Fiber | null {
  6. const updateExpirationTime = workInProgress.expirationTime;
  7. if (current !== null) {
  8. const oldProps = current.memoizedProps;
  9. const newProps = workInProgress.pendingProps;
  10. if (oldProps !== newProps || hasLegacyContextChanged()) {
  11. // If props or context changed, mark the fiber as having performed work.
  12. // This may be unset if the props are determined to be equal later (memo).
  13. didReceiveUpdate = true;
  14. } else if (updateExpirationTime < renderExpirationTime) {
  15. //更新执行的代码
  16. }
  17. } else {
  18. didReceiveUpdate = false;
  19. }
  20. // Before entering the begin phase, clear the expiration time.
  21. workInProgress.expirationTime = NoWork;
  22. switch (workInProgress.tag) {
  23. case IndeterminateComponent: {
  24. const elementType = workInProgress.elementType;
  25. return mountIndeterminateComponent(
  26. current,
  27. workInProgress,
  28. elementType,
  29. renderExpirationTime,
  30. );
  31. }
  32. case FunctionComponent: {
  33. const Component = workInProgress.type;
  34. const unresolvedProps = workInProgress.pendingProps;
  35. const resolvedProps =
  36. workInProgress.elementType === Component
  37. ? unresolvedProps
  38. : resolveDefaultProps(Component, unresolvedProps);
  39. return updateFunctionComponent(
  40. current,
  41. workInProgress,
  42. Component,
  43. resolvedProps,
  44. renderExpirationTime,
  45. );
  46. }
  47. case ClassComponent: {
  48. const Component = workInProgress.type;
  49. const unresolvedProps = workInProgress.pendingProps;
  50. const resolvedProps =
  51. workInProgress.elementType === Component
  52. ? unresolvedProps
  53. : resolveDefaultProps(Component, unresolvedProps);
  54. return updateClassComponent(
  55. current,
  56. workInProgress,
  57. Component,
  58. resolvedProps,
  59. renderExpirationTime,
  60. );
  61. }
  62. case HostRoot:
  63. return updateHostRoot(current, workInProgress, renderExpirationTime);
  64. case HostComponent:
  65. return updateHostComponent(current, workInProgress, renderExpirationTime);
  66. case HostText:
  67. return updateHostText(current, workInProgress);
  68. case IncompleteClassComponent: {
  69. const Component = workInProgress.type;
  70. const unresolvedProps = workInProgress.pendingProps;
  71. const resolvedProps =
  72. workInProgress.elementType === Component
  73. ? unresolvedProps
  74. : resolveDefaultProps(Component, unresolvedProps);
  75. return mountIncompleteClassComponent(
  76. current,
  77. workInProgress,
  78. Component,
  79. resolvedProps,
  80. renderExpirationTime,
  81. );
  82. }
  83. }
  84. }

beginWork 返回的是workInProgress.child

HostRoot

  1. function beginWork(current ,workInProgress , renderExpirationTime){
  2. case HostRoot:
  3. return updateHostRoot(current$$1, workInProgress, renderExpirationTime);
  4. }

第一次渲染时,传入的fiber是RootFiber,类型是HostRoot。示例中的App Fiber是updateHostRoot返回的workInProgress.child。初始一次,之后在app中的操作基本上都属于更新。

  1. function updateHostRoot(current, workInProgress, renderExpirationTime) {
  2. pushHostRootContext(workInProgress);
  3. const updateQueue = workInProgress.updateQueue;
  4. const nextProps = workInProgress.pendingProps;
  5. const prevState = workInProgress.memoizedState;
  6. const prevChildren = prevState !== null ? prevState.element : null;
  7. //更新队列,感兴趣可以自己看下,计算得到 memoizedState
  8. processUpdateQueue(workInProgress, updateQueue, nextProps, null,renderExpirationTime);
  9. const nextState = workInProgress.memoizedState;
  10. const nextChildren = nextState.element;// App的ReactElemnet
  11. if (nextChildren === prevChildren) {//fiber是复用的,会clone
  12. resetHydrationState();
  13. return bailoutOnAlreadyFinishedWork(
  14. current,
  15. workInProgress,
  16. renderExpirationTime,
  17. );
  18. }
  19. const root: FiberRoot = workInProgress.stateNode;
  20. if (
  21. (current === null || current.child === null) &&
  22. root.hydrate &&
  23. enterHydrationState(workInProgress)
  24. ) {//
  25. workInProgress.effectTag |= Placement;
  26. workInProgress.child = mountChildFibers(
  27. workInProgress,
  28. null,
  29. nextChildren,
  30. renderExpirationTime,
  31. );
  32. } else {
  33. //初始执行此处 nextChildren是App ReactElement
  34. reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime);
  35. resetHydrationState();
  36. }
  37. return workInProgress.child;
  38. }

调用栈:updateHostRoot —> reconcileChildren

HostComponent

  1. function beginWork(current ,workInProgress , renderExpirationTime){
  2. case HostComponent:
  3. return updateHostComponent(current, workInProgress, renderExpirationTime);
  4. }
  1. function updateHostComponent(current, workInProgress, renderExpirationTime) {
  2. pushHostContext(workInProgress);
  3. if (current === null) {
  4. tryToClaimNextHydratableInstance(workInProgress);
  5. }
  6. const type = workInProgress.type;
  7. const nextProps = workInProgress.pendingProps;
  8. const prevProps = current !== null ? current.memoizedProps : null;
  9. let nextChildren = nextProps.children;
  10. const isDirectTextChild = shouldSetTextContent(type, nextProps);
  11. if (isDirectTextChild) {//只有一个 文本 子节点,此时文本子节点不再转换为fiber
  12. nextChildren = null;
  13. } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {
  14. workInProgress.effectTag |= ContentReset;//文本重置的 effect
  15. }
  16. markRef(current, workInProgress);
  17. // Check the host config to see if the children are offscreen/hidden.
  18. // 在屏幕外的可以不渲染..........
  19. if (renderExpirationTime !== Never &&
  20. workInProgress.mode & ConcurrentMode &&
  21. shouldDeprioritizeSubtree(type, nextProps)
  22. ) {
  23. // Schedule this fiber to re-render at offscreen priority. Then bailout.
  24. workInProgress.expirationTime = workInProgress.childExpirationTime = Never;
  25. return null;
  26. }
  27. //通常会走此处
  28. reconcileChildren(
  29. current,
  30. workInProgress,
  31. nextChildren,
  32. renderExpirationTime,
  33. );
  34. return workInProgress.child;
  35. }

调用栈: updateHostComponent —> reconcileChildren

HostText

  1. function beginWork(current ,workInProgress , renderExpirationTime){
  2. case HostText:
  3. return updateHostText(current, workInProgress);
  4. }
  1. function updateHostText(current, workInProgress) {
  2. if (current === null) {
  3. tryToClaimNextHydratableInstance(workInProgress);
  4. }
  5. return null;
  6. }

updateHostText中的current是一个fiber,且是beginWork中。文本元素一般没有子元素,直接返回null。在workLoop流程中可以知道返回null,接着会调用completeUnitOfWork —> completeWork ,在completeWork 结束当前的work。

ClassComponent

  1. function beginWork(current ,workInProgress , renderExpirationTime){
  2. case ClassComponent: {
  3. const Component = workInProgress.type;
  4. const unresolvedProps = workInProgress.pendingProps;
  5. const resolvedProps =
  6. workInProgress.elementType === Component
  7. ? unresolvedProps
  8. : resolveDefaultProps(Component, unresolvedProps);
  9. return updateClassComponent(
  10. current,workInProgress,Component,resolvedProps,renderExpirationTime
  11. );
  12. }
  13. }
  1. function updateClassComponent(
  2. current: Fiber | null,
  3. workInProgress: Fiber,
  4. Component: any,
  5. nextProps,
  6. renderExpirationTime: ExpirationTime,
  7. ) {
  8. let hasContext;
  9. if (isLegacyContextProvider(Component)) {
  10. hasContext = true;
  11. pushLegacyContextProvider(workInProgress);
  12. } else {
  13. hasContext = false;
  14. }
  15. prepareToReadContext(workInProgress, renderExpirationTime);
  16. const instance = workInProgress.stateNode;
  17. let shouldUpdate;
  18. if (instance === null) {
  19. if (current !== null) {
  20. current.alternate = null;
  21. workInProgress.alternate = null;
  22. // Since this is conceptually a new fiber, schedule a Placement effect
  23. workInProgress.effectTag |= Placement;
  24. }
  25. // In the initial pass we might need to construct the instance.
  26. constructClassInstance(
  27. workInProgress,
  28. Component,
  29. nextProps,
  30. renderExpirationTime,
  31. );
  32. mountClassInstance(
  33. workInProgress,
  34. Component,
  35. nextProps,
  36. renderExpirationTime,
  37. );
  38. shouldUpdate = true;
  39. } else if (current === null) {
  40. // In a resume, we'll already have an instance we can reuse.
  41. shouldUpdate = resumeMountClassInstance(
  42. workInProgress,
  43. Component,
  44. nextProps,
  45. renderExpirationTime,
  46. );
  47. } else {
  48. shouldUpdate = updateClassInstance(
  49. current,
  50. workInProgress,
  51. Component,
  52. nextProps,
  53. renderExpirationTime,
  54. );
  55. }
  56. const nextUnitOfWork = finishClassComponent(
  57. current,
  58. workInProgress,
  59. Component,
  60. shouldUpdate,
  61. hasContext,
  62. renderExpirationTime,
  63. );
  64. return nextUnitOfWork;
  65. }

组件的渲染可分为initial、update两阶段。initial阶段执行:constructClassInstance 、mountClassInstance;update阶段执行updateClassInstance。阶段执行完后执行 finishClassComponent,组件是否更新还依赖于shouldUpdate参数。

initial-constructClassInstance

执行class 的construct 方法,创建class 实例

  1. function constructClassInstance(
  2. workInProgress: Fiber,
  3. ctor: any,
  4. props: any,
  5. renderExpirationTime: ExpirationTime,
  6. ): any {
  7. let isLegacyContextConsumer = false;
  8. let unmaskedContext = emptyContextObject;
  9. let context = null;
  10. const contextType = ctor.contextType;
  11. if (typeof contextType === 'object' && contextType !== null) {
  12. context = readContext((contextType: any));
  13. } else {
  14. unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
  15. const contextTypes = ctor.contextTypes;
  16. isLegacyContextConsumer =
  17. contextTypes !== null && contextTypes !== undefined;
  18. context = isLegacyContextConsumer
  19. ? getMaskedContext(workInProgress, unmaskedContext)
  20. : emptyContextObject;
  21. }
  22. const instance = new ctor(props, context);//执行classComponent的实例
  23. const state = (workInProgress.memoizedState =
  24. instance.state !== null && instance.state !== undefined
  25. ? instance.state
  26. : null);//workInProgress.memoizedState是新的state
  27. adoptClassInstance(workInProgress, instance);
  28. if (isLegacyContextConsumer) {
  29. cacheContext(workInProgress, unmaskedContext, context);
  30. }
  31. return instance;
  32. }

initial-mountClassInstance

  1. // Invokes the mount life-cycles on a previously never rendered instance.
  2. function mountClassInstance(
  3. workInProgress: Fiber,
  4. ctor: any,
  5. newProps: any,
  6. renderExpirationTime: ExpirationTime,
  7. ): void {
  8. const instance = workInProgress.stateNode;
  9. instance.props = newProps;
  10. instance.state = workInProgress.memoizedState;
  11. instance.refs = emptyRefsObject;
  12. const contextType = ctor.contextType;
  13. if (typeof contextType === 'object' && contextType !== null) {
  14. instance.context = readContext(contextType);
  15. } else {
  16. const unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
  17. instance.context = getMaskedContext(workInProgress, unmaskedContext);
  18. }
  19. let updateQueue = workInProgress.updateQueue;
  20. if (updateQueue !== null) {//有 更新队列
  21. processUpdateQueue(workInProgress,updateQueue,newProps,instance,renderExpirationTime);
  22. instance.state = workInProgress.memoizedState;
  23. }
  24. const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
  25. if (typeof getDerivedStateFromProps === 'function') {
  26. applyDerivedStateFromProps(workInProgress,ctor,getDerivedStateFromProps,newProps);
  27. instance.state = workInProgress.memoizedState;
  28. }
  29. // In order to support react-lifecycles-compat polyfilled components,
  30. // Unsafe lifecycles should not be invoked for components using the new APIs.
  31. if (
  32. typeof ctor.getDerivedStateFromProps !== 'function' &&
  33. typeof instance.getSnapshotBeforeUpdate !== 'function' &&
  34. (typeof instance.UNSAFE_componentWillMount === 'function' ||
  35. typeof instance.componentWillMount === 'function')
  36. ) {
  37. callComponentWillMount(workInProgress, instance);
  38. // If we had additional state updates during this life-cycle, let's
  39. // process them now.
  40. updateQueue = workInProgress.updateQueue;
  41. if (updateQueue !== null) {
  42. processUpdateQueue(workInProgress,updateQueue,newProps,instance,renderExpirationTime);
  43. instance.state = workInProgress.memoizedState;
  44. }
  45. }
  46. if (typeof instance.componentDidMount === 'function') {
  47. workInProgress.effectTag |= Update;
  48. }
  49. }

执行mountClassInstance 中更新队列、执行getDerivedStateFromProps、componentWillMount生命周期,同时为componentDidMount打effectTag。initial 执行mountClassInstance ,更新阶段则主要执行updateClassInstance。

update-updateClassInstance

updateClassInstance时先执行getDerivedStateFromProps 、shouldUpdate= checkShouldComponentUpdate();

  1. / Invokes the update life-cycles and returns false if it shouldn't rerender.
  2. function updateClassInstance(current: Fiber,
  3. workInProgress: Fiber,ctor: any,
  4. newProps: any,renderExpirationTime: ExpirationTime,
  5. ): boolean {
  6. const instance = workInProgress.stateNode;
  7. const oldProps = workInProgress.memoizedProps;
  8. instance.props = orkInProgress.type === workInProgress.elementType ? oldProps
  9. : resolveDefaultProps(workInProgress.type, oldProps);
  10. const oldContext = instance.context;
  11. const contextType = ctor.contextType;
  12. let nextContext;
  13. if (typeof contextType === 'object' && contextType !== null) {
  14. nextContext = readContext(contextType);
  15. } else {
  16. const nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
  17. nextContext = getMaskedContext(workInProgress, nextUnmaskedContext);
  18. }
  19. const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
  20. const hasNewLifecycles =
  21. typeof getDerivedStateFromProps === 'function' ||
  22. typeof instance.getSnapshotBeforeUpdate === 'function';
  23. // In order to support react-lifecycles-compat polyfilled components,
  24. // Unsafe lifecycles should not be invoked for components using the new APIs.
  25. if (!hasNewLifecycles &&(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
  26. typeof instance.componentWillReceiveProps === 'function')
  27. ) {
  28. if (oldProps !== newProps || oldContext !== nextContext) {
  29. callComponentWillReceiveProps( workInProgress, instance, newProps,nextContext ;
  30. }
  31. }
  32. resetHasForceUpdateBeforeProcessing();
  33. const oldState = workInProgress.memoizedState;
  34. let newState = (instance.state = oldState);
  35. let updateQueue = workInProgress.updateQueue;
  36. if (updateQueue !== null) {
  37. processUpdateQueue( workInProgress,updateQueue,newProps,instance,renderExpirationTime);
  38. newState = workInProgress.memoizedState;
  39. }
  40. if (oldProps === newProps && oldState === newState && !hasContextChanged() &&
  41. !checkHasForceUpdateAfterProcessing()
  42. ) {
  43. // If an update was already in progress, we should schedule an Update
  44. // effect even though we're bailing out, so that cWU/cDU are called.
  45. if (typeof instance.componentDidUpdate === 'function') {
  46. if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
  47. workInProgress.effectTag |= Update;
  48. }
  49. }
  50. if (typeof instance.getSnapshotBeforeUpdate === 'function') {
  51. if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
  52. workInProgress.effectTag |= Snapshot;
  53. }
  54. }
  55. return false; //返回false,不向下执行
  56. }
  57. if (typeof getDerivedStateFromProps === 'function') {
  58. applyDerivedStateFromProps(
  59. workInProgress,
  60. ctor,
  61. getDerivedStateFromProps,
  62. newProps,
  63. );
  64. newState = workInProgress.memoizedState;
  65. }
  66. const shouldUpdate =
  67. checkHasForceUpdateAfterProcessing() ||
  68. checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState,
  69. newState, nextContext);
  70. if (shouldUpdate) {
  71. // In order to support react-lifecycles-compat polyfilled components,
  72. // Unsafe lifecycles should not be invoked for components using the new APIs.
  73. if (
  74. !hasNewLifecycles &&
  75. (typeof instance.UNSAFE_componentWillUpdate === 'function' ||
  76. typeof instance.componentWillUpdate === 'function')
  77. ) {
  78. startPhaseTimer(workInProgress, 'componentWillUpdate');
  79. if (typeof instance.componentWillUpdate === 'function') {
  80. instance.componentWillUpdate(newProps, newState, nextContext);
  81. }
  82. if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
  83. instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);
  84. }
  85. stopPhaseTimer();
  86. }
  87. if (typeof instance.componentDidUpdate === 'function') {
  88. workInProgress.effectTag |= Update;
  89. }
  90. if (typeof instance.getSnapshotBeforeUpdate === 'function') {
  91. workInProgress.effectTag |= Snapshot;
  92. }
  93. } else {
  94. // If an update was already in progress, we should schedule an Update
  95. // effect even though we're bailing out, so that cWU/cDU are called.
  96. if (typeof instance.componentDidUpdate === 'function') {
  97. if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
  98. workInProgress.effectTag |= Update;
  99. }
  100. }
  101. if (typeof instance.getSnapshotBeforeUpdate === 'function') {
  102. if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
  103. workInProgress.effectTag |= Snapshot;
  104. }
  105. }
  106. // If shouldComponentUpdate returned false, we should still update the
  107. // memoized props/state to indicate that this work can be reused.
  108. workInProgress.memoizedProps = newProps;
  109. workInProgress.memoizedState = newState;
  110. }
  111. // Update the existing instance's state, props, and context pointers even
  112. // if shouldComponentUpdate returns false.
  113. instance.props = newProps;
  114. instance.state = newState;
  115. instance.context = nextContext;
  116. return shouldUpdate;
  117. }

componentDidUpdate和getSnapshotBeforeUpdate是标记,componentWillUpdate是调用。返回的值是boolean值。

finishClassComponent

  1. function finishClassComponent(
  2. current: Fiber | null,
  3. workInProgress: Fiber,
  4. Component: any,
  5. shouldUpdate: boolean,
  6. hasContext: boolean,
  7. renderExpirationTime: ExpirationTime,
  8. ) {
  9. // Refs should update even if shouldComponentUpdate returns false
  10. markRef(current, workInProgress);
  11. const didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect;
  12. if (!shouldUpdate && !didCaptureError) {
  13. // Context providers should defer to sCU for rendering
  14. if (hasContext) {
  15. invalidateContextProvider(workInProgress, Component, false);
  16. }
  17. return bailoutOnAlreadyFinishedWork(current,workInProgress,renderExpirationTime);
  18. }
  19. const instance = workInProgress.stateNode;
  20. // Rerender
  21. ReactCurrentOwner.current = workInProgress;
  22. let nextChildren;
  23. if (didCaptureError &&
  24. typeof Component.getDerivedStateFromError !== 'function'
  25. ) {
  26. // If we captured an error, but getDerivedStateFrom catch is not defined,
  27. // unmount all the children. componentDidCatch will schedule an update to
  28. // re-render a fallback. This is temporary until we migrate everyone to
  29. // the new API.
  30. // TODO: Warn in a future release.
  31. nextChildren = null;
  32. if (enableProfilerTimer) {
  33. stopProfilerTimerIfRunning(workInProgress);
  34. }
  35. } else {
  36. nextChildren = instance.render();
  37. }
  38. // React DevTools reads this flag.
  39. workInProgress.effectTag |= PerformedWork;
  40. if (current !== null && didCaptureError) {
  41. // If we're recovering from an error, reconcile without reusing any of
  42. // the existing children. Conceptually, the normal children and the children
  43. // that are shown on error are two different sets, so we shouldn't reuse
  44. // normal children even if their identities match.
  45. forceUnmountCurrentAndReconcile(current, workInProgress,nextChildren,renderExpirationTime);
  46. } else {
  47. reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime);
  48. }
  49. workInProgress.memoizedState = instance.state;
  50. if (hasContext) {
  51. invalidateContextProvider(workInProgress, Component, true);
  52. }
  53. return workInProgress.child;
  54. }

finishClassComponent中的 shouldUpdate = false,相当于组件 shouldComponentUpdate 返回false,组件不做更新。
调用栈: updateClassComponent—> reconcileChildren;

FunctionComponent

  1. function beginWork(current ,workInProgress , renderExpirationTime){
  2. case FunctionComponent: {
  3. const Component = workInProgress.type;
  4. const unresolvedProps = workInProgress.pendingProps;
  5. const resolvedProps =
  6. workInProgress.elementType === Component
  7. ? unresolvedProps
  8. : resolveDefaultProps(Component, unresolvedProps);
  9. return updateFunctionComponent(
  10. current,workInProgress,Component,resolvedProps,renderExpirationTime
  11. );
  12. }
  13. }
  1. function updateFunctionComponent(
  2. current,workInProgress,Component,nextProps: any,renderExpirationTime
  3. ) {
  4. const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
  5. const context = getMaskedContext(workInProgress, unmaskedContext);
  6. let nextChildren;
  7. prepareToReadContext(workInProgress, renderExpirationTime);
  8. nextChildren = renderWithHooks(current,workInProgress,Component,nextProps,
  9. context, renderExpirationTime);
  10. if (current !== null && !didReceiveUpdate) {//beginWork的值
  11. bailoutHooks(current, workInProgress, renderExpirationTime);
  12. return bailoutOnAlreadyFinishedWork(current,workInProgress,renderExpirationTime);
  13. }
  14. // React DevTools reads this flag.
  15. workInProgress.effectTag |= PerformedWork;
  16. reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime);
  17. return workInProgress.child;
  18. }

调用栈: updateFunctionComponent —> reconcileChildren

IndeterminateComponent

  1. function mountIndeterminateComponent(
  2. _current,
  3. workInProgress,
  4. Component,
  5. renderExpirationTime,
  6. ) {
  7. if (_current !== null) {
  8. // An indeterminate component only mounts if it suspended inside a non-
  9. // concurrent tree, in an inconsistent state. We want to treat it like
  10. // a new mount, even though an empty version of it already committed.
  11. // Disconnect the alternate pointers.
  12. _current.alternate = null;
  13. workInProgress.alternate = null;
  14. // Since this is conceptually a new fiber, schedule a Placement effect
  15. workInProgress.effectTag |= Placement;
  16. }
  17. const props = workInProgress.pendingProps;
  18. const unmaskedContext = getUnmaskedContext(workInProgress, Component, false);
  19. const context = getMaskedContext(workInProgress, unmaskedContext);
  20. prepareToReadContext(workInProgress, renderExpirationTime);
  21. let value = renderWithHooks( null,workInProgress,Component,
  22. props,context,renderExpirationTime);
  23. // React DevTools reads this flag.
  24. workInProgress.effectTag |= PerformedWork;
  25. if (typeof value === 'object' && value !== null &&typeof value.render === 'function' &&
  26. value.$$typeof === undefined
  27. ) {
  28. // Proceed under the assumption that this is a class instance
  29. workInProgress.tag = ClassComponent;
  30. // Throw out any hooks that were used.
  31. resetHooks();
  32. // Push context providers early to prevent context stack mismatches.
  33. // During mounting we don't know the child context yet as the instance doesn't exist.
  34. // We will invalidate the child context in finishClassComponent() right after rendering.
  35. let hasContext = false;
  36. if (isLegacyContextProvider(Component)) {
  37. hasContext = true;
  38. pushLegacyContextProvider(workInProgress);
  39. } else {
  40. hasContext = false;
  41. }
  42. workInProgress.memoizedState =
  43. value.state !== null && value.state !== undefined ? value.state : null;
  44. const getDerivedStateFromProps = Component.getDerivedStateFromProps;
  45. if (typeof getDerivedStateFromProps === 'function') {
  46. applyDerivedStateFromProps(workInProgress,Component,getDerivedStateFromProps, props);
  47. }
  48. adoptClassInstance(workInProgress, value);
  49. mountClassInstance(workInProgress, Component, props, renderExpirationTime);
  50. return finishClassComponent(
  51. null,workInProgress,Component,true,hasContext,renderExpirationTime ;
  52. } else {
  53. // Proceed under the assumption that this is a function component
  54. workInProgress.tag = FunctionComponent;
  55. reconcileChildren(null, workInProgress, value, renderExpirationTime);
  56. return workInProgress.child;
  57. }
  58. }

在createFiberFromTypeAndProps 创建function Component时默认类型为:IndeterminateComponent。在mountIndeterminateComponent中确认是workInProgress.tag并调用相应的方法。
调用栈: mountIndeterminateComponent —> reconcileChildren

想法:这种方式可以将组件变得更加灵活?想象下,组件的属性都是方法组合的。

小结

在beginWork 做了prop和state判断,判断是否更新;updateClassComponent中shouldUpdate判断是否更新;
多数beginWork最后调用的都是 reconcileChildren,同时返回的是workInProgress.child。由workLoop流程可知道work在 completeUnitOfWork 结束。