繁体   English   中英

react-router v5 with router-config:重定向到子路由

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM