[英]react-router v5 with router-config: Redirect to subroute
我有一个应用程序,它在侧边栏(仪表板、报告等)上有所有主要页面。 主页可以包含一个带有导航链接到子路由的 TopBar。 据我所知,如果用户单击带有子路由的路由,它只会呈现顶部栏:他必须在子路由上再次单击。 我想自动渲染第一个子路由。 我怎样才能做到这一点?
const routes = [
{
label: "Dashboard",
path: "/dashboard",
component: DashboardComponent,
},
{
label: "Reporting",
path: "/reporting",
component: ReportSelection,
},
{
label: "Sales Data",
subLabel: "All tracked sales, leads and booked calls",
path: "/sales-data",
routes: [
{
label: "Sales",
path: "/sales-data/sales",
component: () => <SalesComponent calls={false}/>,
},
{
label: "Leads",
path: "/sales-data/leads",
component: LeadsComponent,
},
{
label: "Calls",
path: "/sales-data/calls",
component: () => <SalesComponent calls={true}/>,
},
{
label: "Phone closing",
path: "/sales-data/phone-closing",
component: PhoneClosingComponent,
}
]
},
]
function RouteWithSubRoutes(route) {
return (
<Route
path={route.path}
render={props => {
return (
// pass the sub-routes down to keep nesting
route.routes?.length > 0 ?
<SubPage {...props} route={route} /> :
<route.component {...props} routes={route.routes} />
)}}
/>
);
}
/**
* You may have some routes with child routes, such as "sales-data" route which has four subroutes. In that case, use SubPage component to render a Navbar to the top with links to subroutes.
* @param route The route with subroutes.
* @returns
*/
function SubPage({ route }) {
console.log(route);
return (
<div>
<HPageHeader title={route.label} subtitle={route.subLabel}>
{route.routes.map((route, _idx) => (
<NavLink to={route.path}>{route.label}</NavLink>
))}
</HPageHeader>
<Switch>
{route.routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</Switch>
</div>
);
}
/**
* This component is the root of the application. It contains :
* - The router
* - The topbar
* - The Sidebar, which contain Links to the first nodes of the app.
* - The switch, who manage the component to render according to the route.
*/
export const App: React.FC = () => {
const [collapsed, setCollapsed] = React.useState<boolean>(false);
return (
<HashRouter basename="/mh">
<TopbarComponent
onToggleCollapse={() => setCollapsed(collapsed => !collapsed)}
></TopbarComponent>
<SidebarComponent routes={routes} collapsed={collapsed}/>
<Switch>
<div style={{marginLeft: collapsed ? "64px" : "220px"}}>
{routes.map((route, idx) => (
<RouteWithSubRoutes key={idx} {...route}/>
))}
</div>
</Switch>
</HashRouter>
)
}
根据您的描述,听起来您想要一个与索引路由类似的东西,也就是说,当 URL 路径与父路径而不是嵌套的子路径之一匹配时呈现组件。 react-router-dom
v5 Route
组件可以采用一系列路径。 指定父路径以及第一个子路由的路径。
例子:
const routes = [
{
label: "Dashboard",
path: "/dashboard",
component: DashboardComponent,
},
{
label: "Reporting",
path: "/reporting",
component: ReportSelection,
},
{
label: "Sales Data",
subLabel: "All tracked sales, leads and booked calls",
path: "/sales-data",
routes: [
{
label: "Sales",
path: ["/sales-data/sales", "/sales-data"],
component: () => <SalesComponent calls={false} />,
},
{
label: "Leads",
path: "/sales-data/leads",
component: LeadsComponent,
},
{
label: "Calls",
path: "/sales-data/calls",
component: () => <SalesComponent calls={true} />,
},
{
label: "Phone closing",
path: "/sales-data/phone-closing",
component: PhoneClosingComponent,
}
]
},
]
如果路由路径和Switch
组件有任何冲突,您可能希望在Route
组件上使用exact
道具。
只是说我解决了它(使用 v5,v6 使用一个使事情变得更容易的 Outlet 组件),如下所示:
const RouteConfigRenderer = (props: Props) => {
const createTree = (route: RouteDefintion) => {
// It's a main route (a leaf in the route.config tree), or it's a route with child routes
if (route.component) {
// Route with child routes
if (route.routes?.length > 0) {
return (
<Route path={route.path}>
<route.component {...route as any} ></route.component>
<div style={{overflow: "scroll", height: "calc(100vh - 188px)"}}>
<Switch>
{route.routes?.map(r => createTree(r))}
<Redirect to={`${RouterUtils.getRedirect(route.routes).path}`}/>
</Switch>
</div>
</Route>
)
} else { // It's a main route (a leaf in the route.config tree)
return <Route path={route.path}>
<route.component {...route as any} ></route.component>
</Route>
}
} else { // It's a index route
return (
<Route path={route.path}>
<Switch >
{route.routes?.map(r => createTree(r))}
<Redirect to={`${RouterUtils.getRedirect(route.routes).path}`}/>
</Switch>
</Route>
)
}
}
return (
<Switch>
{props.routes.map(r => createTree(r))}
<Redirect to={`${RouterUtils.getFirstRedirect().path}`}/>
</Switch>
)
}
RouteConfig 看起来像这样
const routes = [{
path: "/reporting",
routes: [
{
path: "/reporting/:type",
component: () => <ReportComponent/>
},
{
path: "/reporting",
component: ReportSelection
},
]
},
{
path: "/sales-data",
component: IndexNavBarComponent,
routes: [
{
path: "/sales-data/sales",
component: () => <SalesComponent calls={false}/>,
},
{
path: "/sales-data/leads",
component: LeadsComponent,
},
{
path: "/sales-data/calls",
component: () => <SalesComponent calls={true}/>,
},
{
path: "/sales-data/phone-closing",
component: PhoneClosingComponent,
}
]
}
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.