react源码中那些小而美的函数之getComponentNameFromFiber

111 阅读2分钟
function getComponentNameFromFiber(fiber) {
  var tag = fiber.tag,
      type = fiber.type;

  switch (tag) {
    case CacheComponent:
      return 'Cache';

    case ContextConsumer:
      var context = type;
      return getContextName$1(context) + '.Consumer';

    case ContextProvider:
      var provider = type;
      return getContextName$1(provider._context) + '.Provider';

    case DehydratedFragment:
      return 'DehydratedFragment';

    case ForwardRef:
      return getWrappedName$1(type, type.render, 'ForwardRef');

    case Fragment:
      return 'Fragment';

    case HostComponent:
      return type;

    case HostPortal:
      return 'Portal';

    case HostRoot:
      return 'Root';

    case HostText:
      return 'Text';

    case LazyComponent:
      return getComponentNameFromType(type);

    case Mode:
      if (type === REACT_STRICT_MODE_TYPE) {
        return 'StrictMode';
      }

      return 'Mode';

    case OffscreenComponent:
      return 'Offscreen';

    case Profiler:
      return 'Profiler';

    case ScopeComponent:
      return 'Scope';

    case SuspenseComponent:
      return 'Suspense';

    case SuspenseListComponent:
      return 'SuspenseList';

    case TracingMarkerComponent:
      return 'TracingMarker';

    case ClassComponent:
    case FunctionComponent:
    case IncompleteClassComponent:
    case IndeterminateComponent:
    case MemoComponent:
    case SimpleMemoComponent:
      if (typeof type === 'function') {
        return type.displayName || type.name || null;
      }

      if (typeof type === 'string') {
        return type;
      }

      break;
  }

  return null;
}

getComponentNameFromFiber 函数根据不同的 Fiber 节点类型(tag)返回相应的组件名称时,具体情况如下:

  1. CacheComponent

    • 返回值:'Cache'
  2. ContextConsumer

    • 获取 context 对象的名称。
    • 返回值:context.Consumer
  3. ContextProvider

    • 获取 provider 对象的 _context 的名称。
    • 返回值:provider._context.Provider
  4. DehydratedFragment

    • 返回值:'DehydratedFragment'
  5. ForwardRef

    • 获取 type 对象的名称,并以 ForwardRef 包裹。
    • 返回值:'ForwardRef(type)'
  6. Fragment

    • 返回值:'Fragment'
  7. HostComponent

    • 返回值:type(Host component 的类型,如 'div'
  8. HostPortal

    • 返回值:'Portal'
  9. HostRoot

    • 返回值:'Root'
  10. HostText

    • 返回值:'Text'
  11. LazyComponent

    • 获取 type 对象的名称。
    • 返回值:type 的名称
  12. Mode

    • 如果 typeREACT_STRICT_MODE_TYPE,返回 'StrictMode',否则返回 'Mode'
  13. OffscreenComponent

    • 返回值:'Offscreen'
  14. Profiler

    • 返回值:'Profiler'
  15. ScopeComponent

    • 返回值:'Scope'
  16. SuspenseComponent

    • 返回值:'Suspense'
  17. SuspenseListComponent

    • 返回值:'SuspenseList'
  18. TracingMarkerComponent

    • 返回值:'TracingMarker'
  19. ClassComponent, FunctionComponent, IncompleteClassComponent, IndeterminateComponent, MemoComponent, SimpleMemoComponent

    • 如果 type 是函数,则返回函数的 displayNamename,否则返回 type 本身。

这个函数的作用是通过分析 Fiber 节点的类型,为该节点对应的 React 元素返回一个合适的名称。

好的,下面是一些可能的例子:

  1. 对于一个 Class Component:

    class MyComponent extends React.Component {
      // ...
    }
    
    • 对应的 Fiber 节点类型是 ClassComponenttypeMyComponent
    • 返回值:'MyComponent'
  2. 对于一个 Function Component:

    function FunctionalComponent() {
      // ...
    }
    
    • 对应的 Fiber 节点类型是 FunctionComponenttypeFunctionalComponent
    • 返回值:'FunctionalComponent'
  3. 对于一个 ForwardRef:

    const MyComponent = React.forwardRef((props, ref) => {
      // ...
    });
    
    • 对应的 Fiber 节点类型是 ForwardReftype 是一个函数。
    • 返回值:'ForwardRef([Function])'
  4. 对于一个 Host Component(DOM 元素):

    <div>Hello World!</div>
    
    • 对应的 Fiber 节点类型是 HostComponenttype'div'
    • 返回值:'div'
  5. 对于一个 Context Consumer:

    const MyContextConsumer = () => {
      const value = useContext(MyContext);
      // ...
    };
    
    • 对应的 Fiber 节点类型是 ContextConsumertypeMyContext
    • 返回值:'MyContext.Consumer'

这些例子展示了在不同情况下 getComponentNameFromFiber 函数的返回值。请注意,实际返回值可能会受到 React 版本和配置的影响。