国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

React16源碼: React中的IndeterminateComponent的源碼實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了React16源碼: React中的IndeterminateComponent的源碼實(shí)現(xiàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

IndeterminateComponent


1 )概述

  • 這是一個(gè)比較特殊的component的類型, 就是還沒有被指定類型的component
  • 在一個(gè)fibrer被創(chuàng)建的時(shí)候,它的tag可能會(huì)是 IndeterminateComponent
  • 在 packages/react-reconciler/src/ReactFiber.js 中,有一個(gè)方法
  • createFiberFromTypeAndProps 中,一開始就聲明了
    let fiberTag = IndeterminateComponent;
    let resolvedType = type;
    // 一開始
    if (typeof type === 'function') {
      // 在 function 下只是判斷了 constructor是否存在
      // 在不存在的時(shí)候,是否認(rèn)為它是一個(gè) FunctionComponent 呢,實(shí)際上并沒有
      // 實(shí)際上我們寫的任何一個(gè) function component 一開始就是 IndeterminateComponent 類型
      if (shouldConstruct(type)) {
        // 存在,則賦值為 ClassComponent
        fiberTag = ClassComponent;
      }
    } else if (typeof type === 'string') {
      fiberTag = HostComponent;
    } else {
      // 省略
    }
    
  • 在最終調(diào)用 createFiber 創(chuàng)建 Fiber 對(duì)象

2 )源碼

定位到 packages/react-reconciler/src/ReactFiber.js
進(jìn)入 mountIndeterminateComponent 方法文章來源地址http://www.zghlxwxcb.cn/news/detail-811797.html

// 
function mountIndeterminateComponent(
  _current,
  workInProgress,
  Component,
  renderExpirationTime,
) {
  // 首先判斷 _current 是否存在,存在則進(jìn)行初始化操作
  // 因?yàn)橹挥性诘谝淮武秩镜臅r(shí)候,才有 indeterminate component 這種情況
  // 經(jīng)過第一次渲染之后,我們就會(huì)發(fā)現(xiàn) indeterminate component 的具體的類型
  // 這種情況,可能是中途拋出一個(gè) error 或 promise 等情況,比如 Suspense 組件
  // 這時(shí)候初始化是為了 去除 _current 和 workInProgress 相關(guān)聯(lián)系,因?yàn)樾枰匦逻M(jìn)行初次渲染的流程
  if (_current !== null) {
    // An indeterminate component only mounts if it suspended inside a non-
    // concurrent tree, in an inconsistent state. We want to treat it like
    // a new mount, even though an empty version of it already committed.
    // Disconnect the alternate pointers.
    _current.alternate = null;
    workInProgress.alternate = null;
    // Since this is conceptually a new fiber, schedule a Placement effect
    workInProgress.effectTag |= Placement;
  }

  const props = workInProgress.pendingProps;
  const unmaskedContext = getUnmaskedContext(workInProgress, Component, false);
  const context = getMaskedContext(workInProgress, unmaskedContext);

  prepareToReadContext(workInProgress, renderExpirationTime);
  prepareToUseHooks(null, workInProgress, renderExpirationTime);

  let value;

  if (__DEV__) {
    if (
      Component.prototype &&
      typeof Component.prototype.render === 'function'
    ) {
      const componentName = getComponentName(Component) || 'Unknown';

      if (!didWarnAboutBadClass[componentName]) {
        warningWithoutStack(
          false,
          "The <%s /> component appears to have a render method, but doesn't extend React.Component. " +
            'This is likely to cause errors. Change %s to extend React.Component instead.',
          componentName,
          componentName,
        );
        didWarnAboutBadClass[componentName] = true;
      }
    }

    if (workInProgress.mode & StrictMode) {
      ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);
    }

    ReactCurrentOwner.current = workInProgress;
    value = Component(props, context); 
  } else {
    value = Component(props, context); // 調(diào)用 Component 方法
  }
  // React DevTools reads this flag.
  workInProgress.effectTag |= PerformedWork;

  // 符合這個(gè)條件,認(rèn)為是 ClassComponent, 具有 render 方法
  if (
    typeof value === 'object' &&
    value !== null &&
    typeof value.render === 'function' &&
    value.$$typeof === undefined
  ) {
    // Proceed under the assumption that this is a class instance
    workInProgress.tag = ClassComponent; // 這里認(rèn)為它是一個(gè) ClassComponent

    // Throw out any hooks that were used.
    resetHooks();

    // Push context providers early to prevent context stack mismatches.
    // During mounting we don't know the child context yet as the instance doesn't exist.
    // We will invalidate the child context in finishClassComponent() right after rendering.
    let hasContext = false;
    if (isLegacyContextProvider(Component)) {
      hasContext = true;
      pushLegacyContextProvider(workInProgress);
    } else {
      hasContext = false;
    }

    workInProgress.memoizedState =
      value.state !== null && value.state !== undefined ? value.state : null;

    const getDerivedStateFromProps = Component.getDerivedStateFromProps;
    if (typeof getDerivedStateFromProps === 'function') {
      applyDerivedStateFromProps(
        workInProgress,
        Component,
        getDerivedStateFromProps,
        props,
      );
    }

    adoptClassInstance(workInProgress, value);
    mountClassInstance(workInProgress, Component, props, renderExpirationTime);
    return finishClassComponent(
      null,
      workInProgress,
      Component,
      true,
      hasContext,
      renderExpirationTime,
    );
  } else {
    // 否則按照 FunctionComponent 來渲染
    // Proceed under the assumption that this is a function component
    workInProgress.tag = FunctionComponent; 
    value = finishHooks(Component, props, value, context);
    if (__DEV__) {
      if (Component) {
        warningWithoutStack(
          !Component.childContextTypes,
          '%s(...): childContextTypes cannot be defined on a function component.',
          Component.displayName || Component.name || 'Component',
        );
      }
      if (workInProgress.ref !== null) {
        let info = '';
        const ownerName = ReactCurrentFiber.getCurrentFiberOwnerNameInDevOrNull();
        if (ownerName) {
          info += '\n\nCheck the render method of `' + ownerName + '`.';
        }

        let warningKey = ownerName || workInProgress._debugID || '';
        const debugSource = workInProgress._debugSource;
        if (debugSource) {
          warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
        }
        if (!didWarnAboutFunctionRefs[warningKey]) {
          didWarnAboutFunctionRefs[warningKey] = true;
          warning(
            false,
            'Function components cannot be given refs. ' +
              'Attempts to access this ref will fail.%s',
            info,
          );
        }
      }

      if (typeof Component.getDerivedStateFromProps === 'function') {
        const componentName = getComponentName(Component) || 'Unknown';

        if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {
          warningWithoutStack(
            false,
            '%s: Function components do not support getDerivedStateFromProps.',
            componentName,
          );
          didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;
        }
      }

      if (
        typeof Component.contextType === 'object' &&
        Component.contextType !== null
      ) {
        const componentName = getComponentName(Component) || 'Unknown';

        if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {
          warningWithoutStack(
            false,
            '%s: Function components do not support contextType.',
            componentName,
          );
          didWarnAboutContextTypeOnFunctionComponent[componentName] = true;
        }
      }
    }
    reconcileChildren(null, workInProgress, value, renderExpirationTime);
    return workInProgress.child;
  }
}
  • 基于上述判斷條件 能認(rèn)定是一個(gè) ClassComponent,后續(xù)渲染一定會(huì)按照 ClassComponent 進(jìn)行
    • if ( typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined ){}
  • 現(xiàn)在來測(cè)試一下,看下 function component 是否可以執(zhí)行
    import React from 'react'
    
    export default function TestIndeterminationComponent() {
      return {
        componentDidMount() {
          console.log('invoker')
        },
        render() {
          return <span>aaa</span>
        }
      }
    }
    
    • 上述都能正常顯示,以及打印 console 輸出
    • 也就是說,對(duì)于一個(gè) function component, 如果里面 return 的對(duì)象,具有 render 方法
    • 就認(rèn)為它是一個(gè) class component 一樣的類型,去使用它
    • 并且在里面聲明的生命周期方法都會(huì)被它調(diào)用
    • 這是 IndeterminateComponent 的特性
  • 在最初我們渲染的時(shí)候,所有的 function component 都是 IndeterminateComponent 的類型
  • 在第一次渲染之后,我們根據(jù)渲染類型的返回,最終得到具體類型
  • 可以通過 function component 返回一個(gè)對(duì)象的方式去渲染一個(gè)類似 classComponent 這樣的類型
  • 注意,一般不推薦這么寫

到了這里,關(guān)于React16源碼: React中的IndeterminateComponent的源碼實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • React16源碼: React中的performWork的源碼實(shí)現(xiàn)

    performWork 1 )概述 performWork 涉及到在調(diào)度完成,或者同步任務(wù)進(jìn)來之后整個(gè) root 節(jié)點(diǎn)鏈條如何更新 怎么更新一棵 Fiber 樹,它的每一個(gè)節(jié)點(diǎn)是如何被遍歷到,以及如何進(jìn)行更新操作 A. 在執(zhí)行 performWork 時(shí)候,是否有 deadline 的區(qū)分 deadline 是通過 reactschedule 它的一個(gè)時(shí)間片,更新

    2024年01月17日
    瀏覽(20)
  • React16源碼: React中的beginWork的源碼實(shí)現(xiàn)

    beginWork 1 )概述 在 renderRoot 之后,要對(duì)我們的 Fiber 樹每一個(gè)節(jié)點(diǎn)進(jìn)行對(duì)應(yīng)的更新 更新節(jié)點(diǎn)的一個(gè)入口方法,就是 beginWork 這個(gè)入口方法會(huì)有幫助我們?nèi)?yōu)化整棵樹的更新過程 react 它的節(jié)點(diǎn)其實(shí)是非常多的,如果每一次子節(jié)點(diǎn)的一個(gè)更新 就需要每一個(gè)節(jié)點(diǎn)都執(zhí)行一遍更新的話

    2024年01月20日
    瀏覽(24)
  • React16源碼: React中的updateHostRoot的源碼實(shí)現(xiàn)

    HostRoot 的更新 1 )概述 HostRoot 是一個(gè)比較特殊的節(jié)點(diǎn), 因?yàn)樵谝粋€(gè)react應(yīng)用當(dāng)中 它只會(huì)有一個(gè) HostRoot , 它對(duì)應(yīng)的 Fiber 對(duì)象是我們的 RootFiber 對(duì)象 重點(diǎn)在于它的更新過程 2 )源碼 定位到 packages/react-reconciler/src/ReactFiberBeginWork.js#L612 HostRoot 創(chuàng)建更新的過程就是在 ReactFiberReconcile

    2024年01月22日
    瀏覽(29)
  • React16源碼: React中的completeUnitOfWork的源碼實(shí)現(xiàn)

    React16源碼: React中的completeUnitOfWork的源碼實(shí)現(xiàn)

    completeUnitOfWork 1 )概述 各種不同類型組件的一個(gè)更新過程對(duì)應(yīng)的是在執(zhí)行 performUnitOfWork 里面的 beginWork 階段 它是去向下遍歷一棵 fiber 樹的一側(cè)的子節(jié)點(diǎn),然后遍歷到葉子節(jié)點(diǎn)為止,以及 return 自己 child 的這種方式 在 performUnitOfWork 里面,還有一個(gè)方法叫做 completeUnitOfWork 在

    2024年01月23日
    瀏覽(33)
  • React16源碼: React中的setState和forceUpdate源碼實(shí)現(xiàn)

    setState 和 forceUpdate 1 ) 概述 通過 class component 內(nèi)部的 setState ,以及 forceUpdate 去更新一個(gè)組件的過程 在react的應(yīng)用當(dāng)中,我們只有 ReactDOM.render setState ,以及 forceUpdate 這幾種種方式去更新react的應(yīng)用是合理的,其他沒有什么特別常用的方式去更新了 而且react官方推薦的也是用

    2024年01月25日
    瀏覽(22)
  • React16源碼: React中的HostComponent & HostText的源碼實(shí)現(xiàn)

    HostComponent HostText 1 )概述 HostComponent 就是我們dom原生的這些節(jié)點(diǎn), 如: div, span, p 標(biāo)簽這種 使用的是小寫字母開頭的這些節(jié)點(diǎn)一般都認(rèn)為它是一個(gè) HostComponent HostText ,它是單純的文本節(jié)點(diǎn) 主要關(guān)注它們的一個(gè)更新過程 2 )源碼 定位到 packages/react-reconciler/src/ReactFiberBeginWork.js 進(jìn)

    2024年01月24日
    瀏覽(19)
  • React16源碼: React中的reconcileChildIterator和reconcileChildrenArray的源碼實(shí)現(xiàn)

    reconcileChildIterator 和 reconcileChildrenArray 1 )概述 在react更新某一個(gè)節(jié)點(diǎn)的時(shí)候,要根據(jù)這個(gè)節(jié)點(diǎn),它的類型去獲取它的children 比如說如果是 Function Component,它要調(diào)用這個(gè) component 計(jì)算出它的return的屬性 return的屬性可能是一個(gè)數(shù)組,可能是單個(gè)的 ReactElement,可能是 number, string

    2024年01月20日
    瀏覽(46)
  • React16源碼: React中的不同的expirationTime的源碼實(shí)現(xiàn)

    不同的 expirationTime 1 )概述 在React中不僅僅有異步任務(wù) 大部分情況下都是同步的任務(wù),所以會(huì)有不同 expirationTime 的存在 2 )種類 A. Sync 模式,優(yōu)先級(jí)最高 任務(wù)創(chuàng)建完成之后,立馬更新到真正的dom里面 是一個(gè)創(chuàng)建即更新的流程 B. Async 模式, 異步模式 會(huì)有一個(gè)調(diào)度 包含一系列

    2024年02月01日
    瀏覽(19)
  • React16源碼: React中的PortalComponent創(chuàng)建, 調(diào)和, 更新的源碼實(shí)現(xiàn)

    PortalComponent 1 )概述 React Portal之所以叫Portal,因?yàn)樽龅木褪呛汀皞魉烷T”一樣的事情 render到一個(gè)組件里面去,實(shí)際改變的是網(wǎng)頁(yè)上另一處的DOM結(jié)構(gòu) 主要關(guān)注 portal的創(chuàng)建, 調(diào)和, 更新過程 2 )源碼 定位到 packages/react-dom/src/client/ReactDOM.js#L576 這里調(diào)用的是 ReactPortal.createPortal ,

    2024年01月21日
    瀏覽(25)
  • React16源碼: React中的update和updateQueue的源碼實(shí)現(xiàn)

    React中的update和updateQueue 1 )概述 在 ReactDOM.render 過程中,還需要?jiǎng)?chuàng)建一個(gè) update 對(duì)象 update 用于記錄組件狀態(tài)的改變的一個(gè)對(duì)象,它存放于Fiber對(duì)象的 updateQueue 中 updateQueue ,它是一個(gè)單向鏈表的結(jié)構(gòu),一次整體的更新過程當(dāng)中 可能在這個(gè)queue里會(huì)存在多 Update 在這次更新的過

    2024年02月02日
    瀏覽(14)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包