You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript动态渲染组件时获取组件名与导航高亮实现

问题根源

你当前将React.ReactNode类型的JSX元素直接存入state的写法本身就存在设计缺陷,直接访问page.type报TS错误的原因很明确:React.ReactNode是个覆盖范围极广的联合类型,包含字符串、数字、布尔值、React Fragment、Portal等多种不存在type属性的值,TS无法确定你存的page一定是带type字段的React元素,因此会抛出类型错误。
就算你用类型断言强行绕过TS检查,这个方案也无法在生产环境正常运行:构建工具压缩代码时会改写组件的name属性,基于组件名的判断逻辑会直接失效。

最优实现方案

不要在state中存储JSX元素,改为存储当前激活页面的唯一标识,基于标识做组件渲染和导航态判断,完全规避获取组件名的问题,同时做到类型安全、不受代码压缩影响。

实现代码

  1. 首先定义页面标识枚举,统一管理所有可切换页面:
// 所有可切换页面的唯一标识
enum PageType {
  Chats = 'chats',
  Profile = 'profile',
  // 后续新增页面直接在这里加枚举值即可
}
  1. 建立页面标识和对应组件的映射关系:
import UserChats from '@/pages/UserChats';
import UserProfile from '@/pages/UserProfile';

const pageComponentMap = {
  [PageType.Chats]: <UserChats />,
  [PageType.Profile]: <UserProfile />,
};
  1. state中仅存储当前激活的页面标识,初始值设为默认展示的页面:
const [activePage, setActivePage] = useState<PageType>(PageType.Chats);
  1. 页面渲染和导航激活判断直接基于activePage做匹配,逻辑清晰无歧义:
return (
  <div className="app-container">
    {/* 渲染当前激活的页面组件 */}
    <main className="content-area">
      {pageComponentMap[activePage]}
    </main>

    {/* 底部导航栏 */}
    <nav className="bottom-navbar">
      <button
        className={`nav-btn ${activePage === PageType.Chats ? 'nav-btn--active' : ''}`}
        onClick={() => setActivePage(PageType.Chats)}
      >
        消息图标
      </button>
      <button
        className={`nav-btn ${activePage === PageType.Profile ? 'nav-btn--active' : ''}`}
        onClick={() => setActivePage(PageType.Profile)}
      >
        个人中心图标
      </button>
    </nav>
  </div>
);

你只需要给.nav-btn--active类写对应高亮样式(比如修改图标、文字颜色)即可实现导航激活态的动态切换。

不推荐的临时兼容方案

如果你一定要从已存储的ReactNode中取组件名,必须先通过React内置的isValidElement方法做类型收窄,排除非React元素的类型后再访问属性,但请注意该方案无法兼容生产环境代码压缩,仅适合本地调试使用:

import { isValidElement } from 'react';

let componentName: string | null = null;
if (isValidElement(page)) {
  componentName = typeof page.type === 'string'
    ? page.type // 原生dom元素直接取type字符串
    : (page.type as { displayName?: string; name?: string }).displayName || (page.type as { name?: string }).name;
}

内容的提问来源于stack exchange,提问作者José Carlos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:18:14