跳到主要内容

从 Fiber 获取组件名

从 Fiber 获取组件名。

一、从所有者获取组件名称

export function getComponentNameFromOwner(
owner: Fiber | ReactComponentInfo,
): string | null {
if (typeof owner.tag === 'number') {
return getComponentNameFromFiber((owner: any));
}
if (typeof owner.name === 'string') {
return owner.name;
}
return null;
}

二、从 Fiber 获取组件名

export default function getComponentNameFromFiber(fiber: Fiber): string | null {
const { tag, type } = fiber;
switch (tag) {
case ActivityComponent:
return 'Activity';
case CacheComponent:
return 'Cache';
case ContextConsumer:
const consumer: ReactConsumerType<any> = type as any;
return getContextName(consumer._context) + '.Consumer';
case ContextProvider:
const context: ReactContext<any> = type as any;
return getContextName(context);
case DehydratedFragment:
return 'DehydratedFragment';
case ForwardRef:
return getWrappedName(type, type.render, 'ForwardRef');
case Fragment:
return 'Fragment';
case HostHoistable:
case HostSingleton:
case HostComponent:
// Host component type is the display name (e.g. "div", "View")
// 宿主组件类型是显示名称(例如 "div"、"View")
return type;
case HostPortal:
return 'Portal';
case HostRoot:
return 'Root';
case HostText:
return 'Text';
case LazyComponent:
// Name comes from the type in this case; we don't have a tag.
// 在这种情况下,名称来自类型;我们没有标签。
return getComponentNameFromType(type);
case Mode:
if (type === REACT_STRICT_MODE_TYPE) {
// Don't be less specific than shared/getComponentNameFromType
// 不要比 shared/getComponentNameFromType 更不具体
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 ViewTransitionComponent:
if (enableViewTransition) {
return 'ViewTransition';
}
// The display name for these tags come from the user-provided type:
// 这些标签的显示名称来自用户提供的类型:
// Fallthrough
// 贯穿
case IncompleteClassComponent:
case IncompleteFunctionComponent:
if (disableLegacyMode) {
break;
}
// Fallthrough
// 贯穿
case ClassComponent:
case FunctionComponent:
case MemoComponent:
case SimpleMemoComponent:
if (typeof type === 'function') {
return (type as any).displayName || type.name || null;
}
if (typeof type === 'string') {
return type;
}
break;
case LegacyHiddenComponent:
if (enableLegacyHidden) {
return 'LegacyHidden';
}
break;
case Throw: {
if (__DEV__) {
// For an error in child position we use the name of the inner most parent component.
// 对于子位置的错误,我们使用最内层父组件的名称。
// Whether a Server Component or the parent Fiber.
// 无论是服务器组件还是父 Fiber。
const debugInfo = fiber._debugInfo;
if (debugInfo != null) {
for (let i = debugInfo.length - 1; i >= 0; i--) {
if (typeof debugInfo[i].name === 'string') {
return debugInfo[i].name;
}
}
}
if (fiber.return === null) {
return null;
}
return getComponentNameFromFiber(fiber.return);
}
return null;
}
}

return null;
}

三、工具

1.获取封装名称

// Keep in sync with shared/getComponentNameFromType
// 与 shared/getComponentNameFromType 保持同步
function getWrappedName(
outerType: mixed,
innerType: any,
wrapperName: string,
): string {
const functionName = innerType.displayName || innerType.name || '';
return (
(outerType: any).displayName ||
(functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName)
);
}

2.获取上下文名称

// Keep in sync with shared/getComponentNameFromType
// 与 shared/getComponentNameFromType 保持同步
function getContextName(type: ReactContext<any>) {
return type.displayName || 'Context';
}