React render phase parsing II - beginwork process

Go to bed early WQI 2021-10-13 21:01:07
react render phase parsing ii


This is the next issue render Stage article , When resolving mount render Stage " Deliver " Stage ----beginWork function

beginWork Call to

performUnitOfWork Function internal execution beginWork Function of

// ProfileMode  In mode , Speculation is related to performance analysis 
if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
    startProfilerTimer(unitOfWork);
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
    stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
  } else {
    //  Normal process
    //  What has been used fiber,  The updated fiber,  subtreeRenderLanes:  The current lane
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
  }

beginWork$1 function

Deal with some problems in the development environment , And execution beginWork And capture problems . Execute in the development environment performUnitOfWork Will execute beginWork$1 function .

beginWork$1 = function (current, unitOfWork, lanes{
    //  If a component throws an error , We'll replay it synchronously
    //  Dispatch Events , So that the debugger treats it as uncapped
    //  error   see also  ReactErrorUtils  Learn more .
    //  Before entering the start stage , Copy the work in progress to the virtual object
    // Fiber". If  beginWork  Throw out , We'll use it to reset the State .
    // WorkInProgress Copy
    var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);

    try {
      //  call beginWork
      return beginWork(current, unitOfWork, lanes);
    } catch (originalError) {
      //  Capture the error
    }
  };

beginWork Main function

By constantly looping performUnitOfWork Mount child nodes

function beginWork(
  current: Fiber | null,
  workInProgress: Fiber,
  renderLanes: Lanes,
): Fiber | null 
{
  const updateLanes = workInProgress.lanes;

  if (current !== null) {
    const oldProps = current.memoizedProps;
    const newProps = workInProgress.pendingProps;

    if (
      oldProps !== newProps ||
      hasLegacyContextChanged() ||
      //  If the implementation changes due to thermal overload , Force re rendering
      (__DEV__ ? workInProgress.type !== current.type : false)
    ) {
      // ... Processing in the update phase
    } else if (!includesSomeLane(renderLanes, updateLanes)) {
      // 
      //...
    } else {
      if ((current.effectTag & ForceUpdateForLegacySuspense) !== NoEffect) {
        
        didReceiveUpdate = false;
      }
    }
  } else {
  /*  The didReceiveUpdate The variable represents the in this update Fiber Whether the node has changed  */
    didReceiveUpdate = false;
  }
}

mount( First screen rendering ) According to different workInProgress.tag( Component type ) To go to different child nodes to create logic

//  Find different types of components 
switch (workInProgress.tag) {
  case IndeterminateComponent: 
    // ReactDOM.render(<App />, document.getElementById("root")), mount App Components
    return mountIndeterminateComponent(
        current,
        workInProgress,
        workInProgress.type,
        renderLanes,
      );
  case LazyComponent: 
    // ... Omit
  case FunctionComponent: {
      const Component = workInProgress.type;
      const unresolvedProps = workInProgress.pendingProps;
      const resolvedProps =
        workInProgress.elementType === Component
          ? unresolvedProps
          : resolveDefaultProps(Component, unresolvedProps);
      return updateFunctionComponent(
        current,
        workInProgress,
        Component,
        resolvedProps,
        renderLanes,
      );
    }
  case ClassComponent: 
    // ... Omit
  case HostRoot:
    //  When you first create the root node
     return updateHostRoot(current, workInProgress, renderLanes);
  case HostComponent:
    //  Create the root component node
    return updateHostComponent(current, workInProgress, renderLanes);
  case HostText:
    // ... Omit
  // ... Omit other types
}

Create a root node

The first cycle enters beginWork Will create the root node Fiber, perform updateHostRoot function

function updateHostRoot(current, workInProgress, renderLanes{
  //  Push the fiber Stack and tag context , take html label
  //  The main use of fiberStack and valueStatck, call push and pop function
  pushHostRootContext(workInProgress);
  //  obtain workInProgress Related properties of
  const updateQueue = workInProgress.updateQueue;
  const nextProps = workInProgress.pendingProps;
  const prevState = workInProgress.memoizedState;
  const prevChildren = prevState !== null ? prevState.element : null;
  
  //  hold current The update queue of is assigned to workInProgress
  cloneUpdateQueue(current, workInProgress);
  //  to update updateQueue
  processUpdateQueue(workInProgress, nextProps, null, renderLanes);
  const nextState = workInProgress.memoizedState;
  // Caution: React DevTools currently depends on this property
  // being called "element".
  const nextChildren = nextState.element;
  if (nextChildren === prevChildren) {
    resetHydrationState();
    return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
  }
  const root: FiberRoot = workInProgress.stateNode;
  if (root.hydrate && enterHydrationState(workInProgress)) {
    //  Server rendering
  } else {
    // Otherwise reset hydration state in case we aborted and resumed another
    // root.
    reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    resetHydrationState();
  }
  return workInProgress.child;
}

You can know from the inside of the function

  1. processUpdateQueue Processing updates [1], Will be able to workInProgress and current The update queue is executed once
  2. reconcileChildren->reconcileChildFibers( perform diff Algorithm )

reconcileChildFibers

diff The main entrance of the algorithm

function reconcileChildFibers(
    returnFiber: Fiber,
    currentFirstChild: Fiber | null,
    newChild: any,
    lanes: Lanes,
  
): Fiber | null 
{
    // 
    const isUnkeyedTopLevelFragment =
      typeof newChild === 'object' &&
      newChild !== null &&
      newChild.type === REACT_FRAGMENT_TYPE &&
      newChild.key === null;
    if (isUnkeyedTopLevelFragment) {
      newChild = newChild.props.children;
    }

    // Handle object types
    const isObject = typeof newChild === 'object' && newChild !== null;

    if (isObject) {
      //   A single node diff
      switch (newChild.$$typeof) {
        case REACT_ELEMENT_TYPE:
          return placeSingleChild(
            reconcileSingleElement(
              returnFiber,
              currentFirstChild,
              newChild,
              lanes,
            ),
          );
        case REACT_PORTAL_TYPE:
          return placeSingleChild(
            reconcileSinglePortal(
              returnFiber,
              currentFirstChild,
              newChild,
              lanes,
            ),
          );
        case REACT_LAZY_TYPE:
          if (enableLazyElements) {
            const payload = newChild._payload;
            const init = newChild._init;
            // TODO: This function is supposed to be non-recursive.
            return reconcileChildFibers(
              returnFiber,
              currentFirstChild,
              init(payload),
              lanes,
            );
          }
      }
    }

    if (typeof newChild === 'string' || typeof newChild === 'number') {
      return placeSingleChild(
        reconcileSingleTextNode(
          returnFiber,
          currentFirstChild,
          '' + newChild,
          lanes,
        ),
      );
    }

    //  multi-node diff
    if (isArray(newChild)) {
      return reconcileChildrenArray(
        returnFiber,
        currentFirstChild,
        newChild,
        lanes,
      );
    }

    if (getIteratorFn(newChild)) {
      return reconcileChildrenIterator(
        returnFiber,
        currentFirstChild,
        newChild,
        lanes,
      );
    }

    if (isObject) {
      throwOnInvalidObjectType(returnFiber, newChild);
    }

    
    if (typeof newChild === 'undefined' && !isUnkeyedTopLevelFragment) {
      // If the new child is undefined, and the return fiber is a composite
      // component, throw an error. If Fiber return types are disabled,
      // we already threw above.
      switch (returnFiber.tag) {
        case ClassComponent: {
          if (__DEV__) {
            const instance = returnFiber.stateNode;
            if (instance.render._isMockFunction) {
              // We allow auto-mocks to proceed as if they're returning null.
              break;
            }
          }
        }
        
        case FunctionComponent: {
          const Component = returnFiber.type;
          
        }
      }
    }

    // Remaining cases are all treated as empty.
    return deleteRemainingChildren(returnFiber, currentFirstChild);
  }

summary

  1. The process of mounting or updating ,beginWork Phase will pass workInProgress.tag To judge the node tag value , Execute different functions according to different nodes
  2. beginWork->reconcileChildren-> According to whether there is current Tree calls mountChildFibers or reconcileChildFibers
  3. mountChildFibers or reconcileChildFibers Are all based on ChildReconciler The returned function is assigned
  4. The next lecture will look at render Stage " return " Stage completeWork

Reference material

[1]

Pick a pick React The principle of calculating state : https://segmentfault.com/a/1190000039008910.

版权声明
本文为[Go to bed early WQI]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/10/20211001220936273P.html

  1. 为什么说 Node.js 是实时应用程序开发的绝佳选择
  2. PaddlePaddle:在 Serverless 架构上十几行代码实现 OCR 能力
  3. 使用elementui在完成项目中遇到的未知知识点2
  4. On the mechanism of webpack loader
  5. 云原生体系下 Serverless 弹性探索与实践
  6. vue开发技巧
  7. Une fleur merveilleuse de l'histoire de l'industrie des nouveaux véhicules énergétiques, Zhongtai Jiangnan T11, une voiture vintage que vous n'avez jamais vue
  8. 致敬!再见了!LayUI !
  9. Vue安装和卸载
  10. Implement a flipped character with the transform attribute of CSS
  11. 你的第一个 Docker + React + Express 全栈应用
  12. [apprentissage de l'algorithme] 1486. Fonctionnement exclusif du tableau (Java / C / C + + / python / go / Rust)
  13. Zhang Daxian sends a blessing video on xYG relay, showing positive energy in details
  14. 前端技巧-JS元编程ES6 symbol公开符号
  15. Article de 37 ans seul à l'hôpital!Il boitait, soupçonnait d'être blessé, souriait avec douleur
  16. 前端推荐!10分钟带你了解Konva运行原理
  17. npm ERR! iview-project@3.0.0 init: `webpack --progress --config webpack.dev.config.js
  18. 零基础学习Web前端需要注意什么呢?
  19. The Youth League promotes Yiyang Qianxi new film, and the relationship between the two generation and the generation is good. Li Fei is blessed.
  20. PaddlePaddle:在 Serverless 架构上十几行代码实现 OCR 能力
  21. JavaScript数组 几个常用方法
  22. Qu'est - ce qu'il faut remarquer à l'avant - plan Web de l'apprentissage de base zéro?
  23. 暢談this的四種綁定方式
  24. 2021最新Vue面试必胜宝典,大厂面试题解析!
  25. Quatre façons de lier ceci
  26. Préparation au développement de l'extension tagdown
  27. Intervieweur: Parlez - moi des flotteurs CSS
  28. Packaging the View Component Library with rollup
  29. Comment un composant enfant modifie les valeurs passées par le composant parent
  30. Résumé de l'API Express
  31. Optimisation de la structure du Code if else dans le projet
  32. Fonction magique pour résoudre le problème de la fonction maybe - - fonction either
  33. 新手学前端的方法是什么 自学前端该怎么规划
  34. 云原生体系下 Serverless 弹性探索与实践
  35. 如何全方位打造安全高效的HTTPS站点(一)
  36. "Liu Jing dit che 丨 point de vue" est - ce que Custom Road est un MpV digne de la terre?
  37. 从理念到LRU算法实现,起底未来React异步开发方式
  38. Compared with Volvo XC60, Lingke 09 goes out of the spa platform. What would you choose, regardless of the brand?
  39. PaddlePaddle:在 Serverless 架构上十几行代码实现 OCR 能力
  40. 云原生体系下 Serverless 弹性探索与实践
  41. 初学者怎么学Web前端?
  42. react
  43. PaddlePaddle:在 Serverless 架构上十几行代码实现 OCR 能力
  44. JavaScript数组 几个常用方法
  45. Angular 依赖注入 - 全面解析
  46. html_day02
  47. 那些年我们前端面试中经常被问到的题!
  48. The starting price of Ducati multistada V2 in North America is less than 100000 yuan
  49. Hls.js 使用文檔
  50. Hls.js travailler avec des documents
  51. Problèmes liés à la précision JS
  52. Copie une partie des propriétés d'un objet à un autre objet
  53. Multiplexage de modules en vuex
  54. Développement multilingue Android, questions d'entrevue pour le développement de logiciels Android
  55. Chen lushai and her best friend Wang Meng play video, fearless of the pressure of public opinion, and in a good mood to dance in a bare back
  56. # Sass速通(四):继承、混合与函数
  57. Vidéo de développement de combat Android, questions d'entrevue rxjava
  58. Bugatti Chiron maintenance cost exposure! One piece for one car, burn money endlessly
  59. android应用开发基础答案,深入理解Nginx
  60. 做了三年前端,你才知道10分钟就能实现一个PC版魔方游戏