react 项目路由嵌套

651 阅读1分钟

尝试自己写了下react项目的嵌套路由,但是感觉还不是特别的完美,如果代码有什么问题,或者有更好的方案,欢迎探讨指正。

这是我的react和react-router-dom的版本:

"react": "^17.0.2",
"react-router-dom": "^5.2.0",

下面是代码实现

App.tsx

import React, { Suspense } from "react";
import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom";
import { routes, IRouteItem } from "@/routes";

function App() {
  const renderRoutes = (data: IRouteItem[]) => {
    if (data && data.length > 0) {
      return data.map(
        ({ component: Component, path, routes, exact, redirect }) => {
          return routes && routes.length > 0 ? (
            <Route
              key={path}
              path={path}
              render={(props) => (
                <Component {...props}>
                  {redirect ? (
                    <Route
                      exact={exact}
                      path={path}
                      render={() => <Redirect to={redirect} />}
                    />
                  ) : (
                    <Route
                      exact={exact}
                      path={path}
                      render={() => <Redirect to={routes[0].path} />}
                    />
                  )}
                  {renderRoutes(routes)}
                </Component>
              )}
            />
          ) : redirect ? (
            <Route
              key={path}
              path={path}
              exact={exact}
              render={() => <Redirect to={redirect} />}
            />
          ) : (
            <Route
              key={path}
              path={path}
              exact={exact}
              render={(props) => <Component {...props} />}
            />
          );
        }
      );
    }
  };

  return (
    <BrowserRouter>
      <Suspense fallback={null}>
        <Switch>
          {renderRoutes(routes)}
        </Switch>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

routes/index.ts

import { lazy } from "react";

export interface IRouteItem {
  path: string;
  redirect?: string;
  component?: any;
  exact?: boolean;
  routes?: IRouteItem[];
}

export const routes: IRouteItem[] = [
  {
    path: "/",
    redirect: "/a",
    exact: true,
  },
  {
    path: "/a",
    exact: true,
    // redirect: "/a/accountcenter",
    component: lazy(() => import("@/pages/Index")),
    routes: [
      {
        path: "/a/tasklist",
        exact: true,
        component: lazy(() => import("@/pages/TaskList")),
      },
      {
        path: "/a/accountcenter",
        exact: true,
        component: lazy(() => import("@/pages/AccountCenter")),
      },
    ],
  },
  {
    path: "/demo",
    exact: true,
    component: lazy(() => import("@/pages/Demo")),
  },
  {
    path: "*",
    exact: true,
    component: lazy(() => import("@/pages/NotFound")),
  },
];