我正在try 将嵌套路由添加到应用程序中,但老实说,我不知道如何添加.如何将嵌套路由添加到我的应用程序?

这是我的应用程序:

import { Route, Routes } from 'react-router-dom';
import routes, { RouteModel } from './router/routes';
import CustomRoute from './router/CustomRoute';

const renderRoutes = (routes: RouteModel[]) => {
  return routes.map((route, index) => {
    if (route.SubItems && route.SubItems.length > 0) {
      return (
        <Route
          key={index}
          path={route.Path}
          element={
            <CustomRoute path={route.Path}>
              <route.Page />
              {renderRoutes(route.SubItems)}
            </CustomRoute>
          }
        />
      );
    } else {
      return (
        <Route
          key={index}
          path={route.Path}
          element={
            <CustomRoute path={route.Path}>
              <route.Page />
            </CustomRoute>
          }
        />
      );
    }
  });
};

const App = () => {
  return <Routes>{renderRoutes(routes)}</Routes>;
};

export default App;

我的路由是这样的:

import { ComponentType } from 'react';
import CreateCarPage from '../page/car/create/page';
import HomePage from '../page/home/page';
import LoginPage from '../page/login/page';
import ListCarPage from '../page/car/list/page';

export type RouteModel = {
  Path: string;
  Page: ComponentType<any>;
  Text: string;
  SubItems?: RouteModel[];
};

const routes: RouteModel[] = [
  {
    Path: '*',
    Page: HomePage,
    Text: 'Home',
  },
  {
    Path: '/login',
    Page: LoginPage,
    Text: 'Login',
  },
  {
    Path: '/car',
    Page: ListCarPage,
    Text: 'Car',
    SubItems: [
      {
        Path: '/car/create',
        Text: 'Create',
        Page: CreateCarPage,
      },
    ],
  },
];

export default routes;

和我的定制路由:

import { Navigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import Layout from '../component/layout/Layout';

type Props = {
  children: React.ReactNode;
  path: string;
};

const CustomRoute = ({ children, path }: Props) => {
  const { authenticated } = useAuth();

  if (path === '/login') {
    return authenticated ? <Navigate to="/" /> : children;
  }

  return authenticated ? <Layout>{children}</Layout> : <Navigate to="/login" />;
};

export default CustomRoute;

我得到了这个错误:

未捕获的错误:<Route>只能用作<Routes>元素的子元素,不能直接呈现.请把你的<Route>元装在<Routes>元里

推荐答案

renderRoutes返回包含Route个组件的array.这些需要包装在Routes组件中.根级别已经用<Routes>{renderRoutes(routes)}</Routes>处理,route.SubItems的后代路由也需要在Routes中包装.

当被路由的组件呈现派生的路由时,例如在Routes组件中呈现更多的路由时,父路径必然需要将通配符/分隔符"*"附加到该路径,从而派生的路由路径也可以被匹配和呈现.

const renderRoutes = (routes: RouteModel[]) => {
  return routes.map((route, index) => {
    if (route.SubItems && route.SubItems.length > 0) {
      return (
        <Route
          key={index}
          path={`${route.Path}/*`} {/* <-- append wildcard/splat */}
          element={
            <CustomRoute path={route.Path}>
              <route.Page />
              <Routes>
                {renderRoutes(route.SubItems)} {/* <-- wrapped in Routes! */}
              </Routes>
            </CustomRoute>
          }
        />
      );
    } else {
      return (
        <Route
          key={index}
          path={route.Path}
          element={
            <CustomRoute path={route.Path}>
              <route.Page />
            </CustomRoute>
          }
        />
      );
    }
  });
};

通过计算是否有要呈现的子路由,并有条件地将通配符/Splat应用于父路由并有条件地呈现子路由,可以使代码多一点100.

const renderRoutes = (routes: RouteModel[]) => {
  return routes.map((route, index) => {
    const hasSubRoutes = !!route.SubItems?.length;

    return (
      <Route
        key={index}
        path={hasSubRoutes ? route.Path : `${route.Path}/*`}
        element={
          <CustomRoute path={route.Path}>
            <route.Page />
            {hasSubRoutes && (
              <Routes>
                {renderRoutes(route.SubItems)}
              </Routes>
            )}
          </CustomRoute>
        }
      />
    );
  });
};

Typescript相关问答推荐

为什么在将条件返回类型的字符串赋给数字时没有类型错误?

带有微前端的动态React路由问题

如何为父类构造函数中的修饰属性赋值?

contextPaneTitleText类型的参数不能分配给remoteconfig类型的关键参数'""'''

输入元素是类型变体的对象数组的正确方法是什么?'

泛型类型,引用其具有不同类型的属性之一

如何在TypeScript中将一个元组映射(转换)到另一个元组?

类型脚本基于数组作为泛型参数展开类型

如何解决类型T不能用于索引类型{ A:typeof A; B:typeof B;. }'

是否可以基于对象的S属性值[]约束对象的其他属性值用于类型化的对象数组?

是否将自动导入样式从`~/目录/文件`改为`@/目录/文件`?

如何在typescript中为this关键字设置上下文

为什么我的导航在使用Typescript的React Native中不起作用?

类型';字符串|数字';不可分配给类型';未定义';.类型';字符串';不可分配给类型';未定义';

如果判断空值,则基本类型Gaurd不起作用

打印脚本中正则函数和函数表达式的不同类型缩小行为

基于属性值的条件类型

TypeScript:如何使用泛型和子类型创建泛型默认函数?

确保财产存在

可选通用映射器函数出错