簡體   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