React与react-router-dom中如何动态渲染Route路由组件
原因说明
JSX 不会自动将字符串类型的组件名和已导入的自定义组件做绑定:
- 小写开头的JSX标签会被默认解析为原生HTML元素
- 原写法中的
<el.text/>实际是尝试把字符串值作为原生标签渲染,React无法识别为自定义页面组件,因此路由无法生效 - React Router的
Route组件的element属性要求传入合法的React元素实例,不能直接通过字符串拼接生成标签。
实现方案
生产环境优先使用组件映射表方案,不需要改动现有SidebarItems的结构,稳定性和安全性都有保障:
- 首先在路由定义文件中引入所有页面组件
import Educatie from '@/pages/Educatie'; import Experienta from '@/pages/Experienta'; import Judete from '@/pages/Judete'; import Localitati from '@/pages/Localitati'; import TipuriContract from '@/pages/Tipuricontract';
- 建立和SidebarItems的text字段一一对应的组件映射对象
const componentMap = { "Educatie": Educatie, "Experienta": Experienta, "Judete": Judete, "Localitati": Localitati, "Tipuri de contract": TipuriContract }
- 遍历配置时从映射表取出组件,赋值给大写开头的变量后再传入element属性(JSX要求自定义组件标签名必须大写开头),增加兜底逻辑避免配置错误导致页面崩溃
<Routes> { SidebarItems.map(el => { const CurrentPage = componentMap[el.text]; if (!CurrentPage) return null; return <Route key={el.text} path={el.link} element={<CurrentPage />} /> }) } </Routes>
可选优化方案
如果可以调整SidebarItems的配置结构,直接把组件作为配置项存入是更易维护的写法,不需要额外维护映射表:
// 提前引入所有页面组件,省略其他引入示例 import Educatie from '@/pages/Educatie'; // 配置项中直接存入组件引用 export const SidebarItems: Array<SidebarItem> = [ { text: "Educatie", icon: SchoolIcon, link: '/educatie', component: Educatie }, // 其余配置项同理增加component字段 ]; // 渲染时直接读取配置中的组件即可 <Routes> { SidebarItems.map(el => { const CurrentPage = el.component; if (!CurrentPage) return null; return <Route key={el.text} path={el.link} element={<CurrentPage />} /> }) } </Routes>
注意:不要使用
eval、字符串拼接动态import()、new Function()等方式实现动态组件,这类方案存在XSS安全隐患,且生产环境代码压缩混淆后组件名会发生变化,极易出现匹配失败的问题。
内容的提问来源于stack exchange,提问作者Octavian Niculescu
相关产品推荐
相关产品推荐

