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

Next.js15中通过按钮动态渲染React组件并传参的实现方案

React动态渲染侧边面板并传递Props的类型解决方案

问题背景

我实现了一套包含主导航栏(Navbar)、导航链接(NavLinks)和侧边面板的组件结构,面板在Navbar内部渲染。原代码可正常运行,但鼠标悬停ActivePanel时出现类型警告:

Type 'ComponentType<{}>' is not assignable to type 'ReactNode'.

同时需要将从next-auth/react的useSession获取的userID作为props传递给激活的侧边面板。

核心需求

  1. 修复动态渲染组件的类型不匹配警告
  2. 向激活的侧边面板传递userID参数

解决步骤

1. 修正Navbar的状态类型定义

更新useState的泛型约束,明确存储的组件必须接收userID: string类型的props,从根源上对齐类型:

const [ActivePanel, setActivePanel] = useState<React.ComponentType<{userID: string;}> | null>(null);

2. 同步NavLinks的Props类型

调整NavLinks的Props接口,确保setActivePanel的dispatch类型与Navbar中的状态类型完全一致:

interface Props {
  setActivePanel: React.Dispatch<React.SetStateAction<React.ComponentType<{ userID: string}> | null>>;
}

点击逻辑可保持不变(或使用函数式更新进一步确保类型安全):

onClick={() => setActivePanel(item.panelComponent)}

3. 渲染组件实例并传递Props

这是解决类型警告的关键操作:原代码中直接渲染组件类型{ActivePanel}会触发类型不兼容,必须改为渲染组件实例并传入userID:

{ActivePanel && (
  <div className="absolute top-0 left-0 w-full h-screen bg-amber-100/50 backdrop-blur-[2px]">
    <div className="fixed top-0 right-0 min-w-[350px] min-h-screen flex flex-col gap-2 p-5 bg-amber-200 shadow-sm">
      <button
        onClick={() => setActivePanel(null)}
        className="mb-2 text-sm text-gray-500"
      >
        close
      </button>
      {/* 改为组件实例并传递userID */}
      <ActivePanel userID={userID} />
    </div>
  </div>
)}

4. 确保面板组件接收Props

所有侧边面板组件(如PanelOne)需定义对应Props接口,接收userID参数:

// PanelOne.tsx
interface Props {
  userID: string;
}

const PanelOne = ({ userID }: Props) => {
  return <div>Panel One - User ID: {userID}</div>;
};

export default PanelOne;

最终完整代码示例

import { useState } from "react";
import NavLinks from "./NavLinks";

const Navbar = () => {
  // 实际项目中从next-auth的useSession获取
  const userID = "some-userID";
  const [ActivePanel, setActivePanel] = useState<React.ComponentType<{userID: string;}> | null>(null);

  return (
    <>
      <header className="sticky top-0 flex items-center justify-between p-10 ">
        <p>Logo Component</p>
        <NavLinks setActivePanel={setActivePanel} />
      </header>
      {ActivePanel && (
        <div className="absolute top-0 left-0 w-full h-screen bg-amber-100/50 backdrop-blur-[2px]">
          <div className="fixed top-0 right-0 min-w-[350px] min-h-screen flex flex-col gap-2 p-5 bg-amber-200 shadow-sm">
            <button
              onClick={() => setActivePanel(null)}
              className="mb-2 text-sm text-gray-500"
            >
              close
            </button>
            <ActivePanel userID={userID} />
          </div>
        </div>
      )}
    </>
  );
};

export default Navbar;
import { NAV_ITEMS } from "./NAV_ITEMS";

interface Props {
  setActivePanel: React.Dispatch<React.SetStateAction<React.ComponentType<{ userID: string}> | null>>;
}

const NavLinks = ({ setActivePanel }: Props) => {
  return (
    <div className="flex items-center gap-5">
      {NAV_ITEMS.map((item) => (
        <button
          key={item.text}
          onClick={() => setActivePanel(item.panelComponent)}
          className="cursor-pointer flex items-center gap-2 p-2"
        >
          {item.text}
        </button>
      ))}
    </div>
  );
};

export default NavLinks;
import PanelOne from "@/components/sidePanels/PanelOne";
import PanelTwo from "@/components/sidePanels/PanelTwo";
import PanelThree from "@/components/sidePanels/PanelThree";

export const NAV_ITEMS = [
  {
    text: "Panel One",
    panelComponent: PanelOne,
  },
  {
    text: "Panel Two",
    panelComponent: PanelTwo,
  },
  {
    text: "Panel Three",
    panelComponent: PanelThree,
  }
];

内容的提问来源于stack exchange,提问作者Andres Romero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:19:52