我需要在React Router V5中实现嵌套路由。

3

我的任务是希望在访问/路由中嵌套一个路由,这意味着我有一个父级路由访问/,因此我需要在此路由中嵌套,例如/access/add-team,我希望在单击按钮时完成此操作,这意味着当某人单击名为Add Team的按钮时,我将该用户推送到/access/add-team路由,因此路由基于单击而改变,但我的添加团队组件未被渲染,我不确定我是否已经在Layout.js文件中添加了所有内容,我的组件存在于Layout.js中,请告诉我我需要添加什么才能正常工作,我还添加了完整代码链接。

const Layout = lazy(() => import("./Layout"));
const PageNotFound = lazy(() => import("./PageNotFound"));

const isLoggedIn = true;
const PrivateRoute = ({ component: Component, isLoggedIn }) => {
  return (
    <Route
      render={(props) =>
        isLoggedIn ? <Component {...props} /> : <Redirect to="/login" />
      }
    />
  );
};

export const AppRoutes = () => {
  return (
    <HashRouter>
      <React.Suspense fallback={""}>
        <Switch>
          <PrivateRoute path="/" isLoggedIn={isLoggedIn} component={Layout} />
          <Route
            path="*"
            name="Not Found"
            render={(props) => <PageNotFound {...props} />}
          />
        </Switch>
      </React.Suspense>
    </HashRouter>
  );
};

function Layout(props) {
  const history = useHistory();
  const { window } = props;
  const [mobileOpen, setMobileOpen] = React.useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const drawer = (
    <div>
      <Toolbar />
      <Divider />
      <List sx={{ minWidth: 230 }}>
        {newText
          ?.filter((data) => data.permission)
          ?.map((value, index) => (
            <ListItemButton
              key={index}
              sx={{ pt: 1, pb: 1, mt: 3.5 }}
              onClick={() => history.push(value.route)}
            >
              <ListItemIcon>
                <InboxIcon />
              </ListItemIcon>
              <ListItemText primary={value.label} />
            </ListItemButton>
          ))}
      </List>
      <Divider />
    </div>
  );

  const container =
    window !== undefined ? () => window().document.body : undefined;

  return (
    <Box sx={{ display: "flex" }}>
      <CssBaseline />
      <AppBar
        position="fixed"
        sx={{
          width: { sm: `calc(100% - ${drawerWidth}px)` },
          ml: { sm: `${drawerWidth}px` }
        }}
      >
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            edge="start"
            onClick={handleDrawerToggle}
            sx={{ mr: 2, display: { sm: "none" } }}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap component="div">
            Responsive drawer
          </Typography>
        </Toolbar>
      </AppBar>
      <Box
        component="nav"
        sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
        aria-label="mailbox folders"
      >
        <Drawer
          variant="permanent"
          sx={{
            display: { xs: "none", sm: "block" },
            "& .MuiDrawer-paper": {
              boxSizing: "border-box",
              width: drawerWidth
            }
          }}
          open
        >
          {drawer}
        </Drawer>
      </Box>
      <Box
        component="main"
        sx={{
          flexGrow: 1,
          p: 3,
          width: { sm: `calc(100% - ${drawerWidth}px)` }
        }}
      >
        <Toolbar />
        <Suspense fallback={""}>
          <Switch>
            {ROUTES.map((route, idx) => {
              return route.component ? (
                <Route
                  key={idx}
                  path={route.path}
                  exact={route.exact}
                  name={route.name}
                  render={(props) => <route.component {...props} />}
                />
              ) : null;
            })}
            <Redirect exact path="/" to="access" />
            <Route
              path="*"
              name="Not Found"
              render={(props) => <PageNotFound {...props} />}
            />
          </Switch>
        </Suspense>
      </Box>
    </Box>
  );
}

你链接的沙盒中的代码似乎运行正常。在点击“添加团队”按钮后,URL 更新为 "/access/add-team"。那么问题是什么? - Drew Reese
但是添加的团队组件没有被渲染。 - user12302978
我想要渲染我在路由中添加的组件。 - user12302978
单一路由组件可以完美渲染,但在嵌套的路由组件中,在按钮点击时无法渲染该路由。路由已成功更改,但该路由与添加团队页面链接,该页面未能渲染。 - user12302978
1个回答

2
在 `Switch` 组件中,路径的顺序和特异性很重要!您希望将路由从更具体的路径到较不具体的路径进行排序。在本例中,您会先呈现 `"/access"` 路径,而不是任何子路由 `"/access/***"` 的路径,因此它被匹配并呈现,而不是实际匹配 URL 中路径的路由。
为解决此问题,请将 `"/access"` 的路由配置移到更具体的路由下面。
export const ROUTES = [
  // move "/access" route from here
  {
    name: "addTeam",
    path: "/access/add-team",
    component: lazy(() => import("./AddTeam"))
  },
  {
    name: "addUser",
    path: "/access/add-user",
    component: lazy(() => import("./AddUser"))
  },
  // to here
  {
    name: "access",
    path: "/access",
    component: lazy(() => import("./Access"))
  },
  {
    name: "admin",
    path: "/admin",
    component: lazy(() => import("./Admin"))
  }
];

enter image description here


好的,这种方法运行良好,但我需要知道它不会产生任何问题,对吧? - user12302978
@devdeveloper 你指的是哪个问题?路径顺序和特定性吗?如果你不确定或者无法完全控制被映射的路径的顺序,那么你可以选择无条件地应用 exact 属性,这样路径就总是完全匹配 - Drew Reese
我并不是在提及任何问题,只是想了解询问的方式是否正确或者只是临时解决方案。 - user12302978
@devdeveloper 在我专业的意见中,Switch 中的路由应该始终按照特定性的相反顺序排列。如果正确执行,就几乎不需要使用 exact 属性来修改此行为。在 RRDv6 中这当然不是问题,因为路由总是完全匹配,并使用路径分数而不是依赖于特定性和顺序。 - Drew Reese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接