我正在尝试将一组硬编码的<Route />
转换为从config变量动态生成的内容。例如
来自
<Router>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} />
<Route path="/documents" component={Documents} exact />
<Route path="/documents/faq" component={DocFAQ} />
<Route path="/documents/translations" component={Translations} />
</Switch>
</Router>
收件人
const routes = [
{
path: '/',
component: Home,
exact: true
},
{
path: '/about',
component: About
},
{
path: '/documents',
component: Documents,
children: [
{
path: '/faq',
component: DocFAQ
},
{
path: '/translations',
component: Translations
}
]
}
];
const RecursiveRoute = ({ route, parentPath = '' }) => {
const path = parentPath + route.path;
return (
<React.Fragment>
<Route path={path} exact={route.exact || (route.children != null)} component={route.component} />
{route.children && route.children.map((childRoute, i) => <RecursiveRoute key={i} route={childRoute} parentPath={path} />)}
</React.Fragment>
);
};
const Routes = () => (
<Router>
<Switch>
{routes.map((route, i) => <RecursiveRoute key={i} route={route} />)}
</Switch>
</Router>
);
当我在<Router>
之外进行映射调用时,此代码将完全生成我想要的;例如。我可以验证其输出的代码与之前的硬编码块完全相同。但是,当它位于<Switch>
内时,仅映射routes
数组中的第一条路线-不会生成其他任何东西。将日志记录语句放在<RecursiveRoute>
中可以确认这一点。
这是为什么,怎么解决?
另一个奇怪的事情是,如果我将<RecursiveRoute>
的JSX粘贴到map
语句中,它就可以工作(除非在这种情况下我不能使其递归):
<Switch>
{routes.map((route, i) => <Route key={i} path={route.path} exact={route.exact || (route.children != null)} component={route.component} />)}
</Switch>
但是,如果我将其外包给另一个组件,则映射将再次失败。
[编辑]解决方案:
基于mehamasum's answer,将<RecursiveRoute>
从组件更改为函数解决了此问题:
function generateRecursiveRoute(route, parentPath = '') {
const path = parentPath + route.path;
const routeHasChildren = (route.children != null);
const baseHtml = <Route path={path} exact={route.exact || routeHasChildren} component={route.component} key={path} />;
return !routeHasChildren ?
baseHtml :
<React.Fragment key={path}>
{baseHtml}
{route.children.map((childRoute) => generateRecursiveRoute(childRoute, path))}
</React.Fragment>;
}
const Routes = () => (
<Router>
<Switch>
{routes.map((route) => generateRecursiveRoute(route))}
</Switch>
</Router>
);
答案 0 :(得分:1)
Switch
是implemented in such a way,您将多个组件作为子组件提供,它将呈现具有匹配的component
的第一个组件path
。因此,如果您提供的不是Route子项(没有path
和component
道具的子项),则需要确保在其中编写渲染逻辑。因为Switch
不知道该做什么,因为它没有看到与该孩子相关的component
或render
道具。
因此,当您直接映射到Route
时,它们正在工作,但是当您映射到RecursiveRoute
时,它失败了。它上面没有path
也没有component
,对吧?
我对您的代码做了一些更新,以便将路由直接呈现为Switch
的子代:
// refactor of RecursiveRoute to
// use it as an utility function, not as component
const getRecursiveRoute = route => {
if (route.children) {
const RootComponent = route.component;
return (
<Route
key={route.path}
path={route.path}
render={props => {
return (
<React.Fragment>
{/* render the root matching component*/}
<RootComponent {...props} />
{/* render the subroutes */}
{/* TODO: consider having a Switch here too */}
{route.children.map(route =>
getRecursiveRoute({
...route,
path: props.match.url + route.path
})
)}
</React.Fragment>
);
}}
/>
);
}
return (
<Route
key={route.path}
path={route.path}
exact={route.exact || route.children != null}
component={route.component}
/>
);
};
const Routes = () => {
return (
<Router>
<Switch>{routes.map(route => getRecursiveRoute(route))}</Switch>
</Router>
);
};
您可能必须修复一些有关精确路由的极端情况。希望对您有所帮助。