1

我正在尝试在我的反应应用程序中实现嵌套路由我的根 app.jsx 文件中的路由是这样定义的。

    <>
      <Router>
        <DrawerContextProvider>
        <Appbar />
        <Switch>
          <Route exact path='/admin'>
            <Admin/>
          </Route>
          <Route path='/technician' component={Technician} />
          <Route path='/accountmanager' component={AccountManager} />
        </Switch>
        </DrawerContextProvider>
      </Router>
    </>

这是我的管理组件中的代码

function Admin() {
    const classes = useStyles();
    const { open } = useContext(DrawerContext)
    const { url, path } = useRouteMatch();

    return (
        <>
            <SideMenu iconsandnames={iconsandnames} />
            <div>
                <main
                    className={clsx(classes.content, {
                        [classes.contentShift]: open,
                    })}
                >
                    <div className={classes.drawerHeader} />
                    <Switch>
                        <Route exact path={path} >
                            <Dashboard />
                        </Route>
                        <Route  path={`${path}/:id`} >
                            <Outlet />
                        </Route>
                    </Switch>
                </main>
            </div>
        </>
    )
}

function Outlet() {
    const { id } = useParams();
    console.log(id);

    return (
        <div>
          <h3>{id}</h3>
        </div>
      );

}

这是我的侧边菜单组件中的代码

export default function MiniDrawer({ iconsandnames }, props) {
    const classes = useStyles();
    const theme = useTheme();
    const { url, path } = useRouteMatch();
    const { open, handleDrawerClose } = useContext(DrawerContext)


    return (
        <div >
            <Drawer
                variant="permanent"
                className={clsx(classes.drawer, {
                    [classes.drawerOpen]: open,
                    [classes.drawerClose]: !open,
                })}
                classes={{
                    paper: clsx({
                        [classes.drawerOpen]: open,
                        [classes.drawerClose]: !open,
                    }),
                }}
            >
                <div className={classes.toolbar}>
                    <IconButton onClick={handleDrawerClose}>
                        {theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
                    </IconButton>
                </div>
                <Divider />
                <List>
                    {iconsandnames.map((data) => (
                        data.text == "Home" ? (
                            <Link to={url}>
                            <ListItem button key={data.text} >
                                <ListItemIcon><Icon>{data.iconname}</Icon></ListItemIcon>
                                <ListItemText primary={data.text} />
                            </ListItem>
                        </Link>):
(                        <Link to={`${url}/${data.route}`}>
                            <ListItem button key={data.text} >
                                <ListItemIcon><Icon>{data.iconname}</Icon></ListItemIcon>
                                <ListItemText primary={data.text} />
                            </ListItem>
                        </Link>)
                    ))}
                </List>
            </Drawer>
        </div>
    );
}

这是我要传递到侧面菜单的图标和名称数组

const iconsandnames = [
    {
        iconname: 'home',
        text: 'Home',
        route: 'home'
    },
    {
        iconname: 'rounded_corner',
        text: 'Projects',
        route: 'projects'
    },
    {
        iconname: 'account_box',
        text: 'Account managers',
        route: 'accountmanagers'
    },
    {
        iconname: 'build',
        text: 'Contractors',
        route: 'contractors'
    },
    {
        iconname: 'perm_identity',
        text: 'Clients',
        route: 'clients'
    },
    {
        iconname: 'work_outline',
        text: 'Work Orders',
        route: 'workorders'
    },
    {
        iconname: 'preview',
        text: 'Additional',
        route: 'additional'
    },
]

http://localhost:3000/admin 给我看 在此处输入图像描述

http://localhost:3000/admin/projects 显示我 在此处输入图像描述

理想情况下,当我切换路线时,侧边菜单不应该消失,而是在这里消失。关于可能是什么问题以及如何解决它的任何想法?

4

1 回答 1

2

问题

您正在exact“/admin”路径上指定道具,因此任何嵌套路由都无法再匹配和呈现。

<Route exact path='/admin'>
  <Admin/>
</Route>

行政

<Switch>
  <Route exact path={path} > // <-- can match
    <Dashboard />
  </Route>
  <Route  path={`${path}/:id`} > // <-- can't match
    <Outlet />
  </Route>
</Switch>

解决方案

将组件渲染Route为时Switch,路径顺序和特异性很重要。您需要将路径从更具体到不太具体排序,以便让更具体的路径有机会在不太具体的路径之前首先匹配和渲染。

路由 -exact从“/admin”路由中删除道具,以便可以匹配任何嵌套路由。

<>
  <Router>
    <DrawerContextProvider>
    <Appbar />
    <Switch>
      <Route path='/admin'>
        <Admin/>
      </Route>
      <Route path='/technician' component={Technician} />
      <Route path='/accountmanager' component={AccountManager} />
    </Switch>
    </DrawerContextProvider>
  </Router>
</>

管理员 - 按特异性重新排序路线。

<Switch>
  <Route path={`${path}/:id`} >
    <Outlet />
  </Route>
  <Route path={path} >
    <Dashboard />
  </Route>
</Switch>
于 2021-07-19T08:20:38.303 回答