React中如何基于state动态生成函数式组件声明?
React动态渲染组件的解决方案
React不支持直接用字符串作为组件名在JSX中渲染,<{component} />这种写法不符合JSX语法规范——JSX要求组件必须是大写开头的React组件引用,而非字符串。以下是具体解决步骤:
1. 导入所有需要动态渲染的组件
先把Menus列表中提到的所有组件导入到SideBar.jsx中:
import { useState } from 'react'; import HomePage from './HomePage'; import Notifications from './Notifications'; import Members from './Members'; import Events from './Events'; import Staff from './Staff'; import Services from './Services'; import Reports from './Reports'; import Settings from './Settings';
2. 创建组件映射表
建立字符串(对应Menus中的title)与实际组件的对应关系,方便通过state值快速匹配组件:
function SideBar() { // ... 原有state和Menus数组 const ComponentMap = { HomePage, Notifications, Members, Events, Staff, Services, Reports, Settings }; // ... 后续代码 }
3. 动态渲染组件
从映射表中取出当前要渲染的组件,判断存在后再渲染:
return ( <div className="flex"> {/* ... 原有侧边栏代码 */} <div className="h-screen flex-1 p-7"> {/* 动态修改页面标题 */} <h1 className="text-2xl font-semibold "> {component || 'Home Page'} </h1> {/* 渲染匹配的组件,无匹配时默认显示HomePage */} {ComponentMap[component] ? <ComponentMap[component] /> : <HomePage />} </div> </div> );
完整修改后的SideBar.jsx代码
import { useState } from 'react'; import HomePage from './HomePage'; import Notifications from './Notifications'; import Members from './Members'; import Events from './Events'; import Staff from './Staff'; import Services from './Services'; import Reports from './Reports'; import Settings from './Settings'; function SideBar() { const [open, setOpen] = useState(true); const [component, setComponent] = useState(''); const Menus = [ { id: '1', title: 'HomePage', src: 'Chart_fill' }, { id: '2', title: 'Notifications', src: 'Chat' }, { id: '3', title: 'Members', src: 'User', gap: true }, { id: '4', title: 'Events', src: 'Calendar' }, { id: '5', title: 'Staff', src: 'Search' }, { id: '6', title: 'Services', src: 'Chart' }, { id: '7', title: 'Reports', src: 'Folder', gap: true }, { id: '8', title: 'Settings', src: 'Setting' }, ]; const ComponentMap = { HomePage, Notifications, Members, Events, Staff, Services, Reports, Settings }; return ( <div className="flex"> <div className={` ${open ? 'w-72' : 'w-20 '} bg-dark-purple h-screen p-5 pt-8 relative duration-300`} > <img src={require('../assets/control.png')} alt="Missing Icon" className={`absolute cursor-pointer -right-3 top-10 w-7 border-dark-purple border-2 rounded-full ${!open && 'rotate-180'}`} onClick={() => setOpen(!open)} /> <div className="flex gap-x-4 items-center"> <img src={require('../assets/logo.png')} alt="Missing Icon" className={`cursor-pointer duration-500 ${open && 'rotate-[360deg]'}`} /> <h1 className={`text-white origin-left font-medium text-xl duration-200 ${!open && 'scale-0'}`} > ADCA </h1> </div> <ul className="pt-6"> {Menus.map((Menu, index) => ( <li onClick={() => { component !== Menu.title ? setComponent(Menu.title) : setComponent(''); }} key={index} className={`flex rounded-md p-2 cursor-pointer hover:bg-light-white text-gray-300 text-sm items-center gap-x-4 ${Menu.gap ? 'mt-9' : 'mt-2'} ${index === 0 && 'bg-light-white'}`} > <img src={require(`../assets/${Menu.src}.png`)} alt="Missing Icon" /> <span className={`${!open && 'hidden'} origin-left duration-200`}> {Menu.title} </span> </li> ))} </ul> </div> <div className="h-screen flex-1 p-7"> <h1 className="text-2xl font-semibold "> {component || 'Home Page'} </h1> {ComponentMap[component] ? <ComponentMap[component] /> : <HomePage />} </div> </div> ); } export default SideBar;
注意事项
- 映射表的
key必须和Menus数组中的title完全一致,否则无法匹配组件。 - React要求组件名必须大写开头,否则会被当作普通HTML标签解析。
- 可根据需求调整默认渲染内容(比如组件为空时显示空白或提示文本)。
内容的提问来源于stack exchange,提问作者Jess
相关产品推荐
相关产品推荐

