我用路线做了一个小任务,当我在其中输入 /
时在 URL 中,它会将我重定向到登录页面,当我输入 /dashboard
时它将我重定向到具有 Material UI 持久抽屉的仪表板。但我这样做的方式完全错误,因为我在两个组件中使用 browserRouter 但理想情况下,它应该只在根组件中,因此
当我第一次单击抽屉中的某个链接时,它会在仪表板中呈现该组件,但当我刷新页面时,它不会加载任何内容
我看到一个例子here 路由组织得很好,就像我点击登录时它们的 URL 是 auth/login
当我注册时,他们的 URL 是 auth/signup
当我转到仪表板时,仪表板也是如此,他们的 URL 是 dashboard/app
当我点击其他链接项目时,模式是相同的 dashboard/link
.
请参阅上面的示例以了解我想要解释的内容。
你可以看到我的代码 here 也在codesandbox 上
简而言之:我想以这种方式组织我的路线auth/login
auth/signup
dashboard/app
dashboard/profile
等等
我的App.js
import { Switch, Route } from "react-router-dom";
import AppDrawerBar from "./compponents/AppDrawerBar";
import Login from "./pages/Login";
import "./styles.css";
export default function App() {
return (
<div className="App">
<Switch>
<Route exact path="/" exact component={Login} />
<Route path="/dashboard" component={AppDrawerBar} />
</Switch>
</div>
);
}
Login.js
import React from "react";
const Login = () => {
return <h1>Login Page</h1>;
};
export default Login;
Dashboard.js,其中链接默认包含主页组件的路由以及有关 compoenet 的路由
import React from "react";
import clsx from "clsx";
import { makeStyles, useTheme } from "@material-ui/core";
import Drawer from "@material-ui/core/Drawer";
import CssBaseline from "@material-ui/core/CssBaseline";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import List from "@material-ui/core/List";
import Typography from "@material-ui/core/Typography";
import Divider from "@material-ui/core/Divider";
import IconButton from "@material-ui/core/IconButton";
import MenuIcon from "@material-ui/icons/Menu";
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import InboxIcon from "@material-ui/icons/MoveToInbox";
import MailIcon from "@material-ui/icons/Mail";
import Home from "../pages/Home";
import About from "../pages/About";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: "flex"
},
appBar: {
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
menuButton: {
marginRight: theme.spacing(2)
},
hide: {
display: "none"
},
drawer: {
width: drawerWidth,
flexShrink: 0
},
drawerPaper: {
width: drawerWidth
},
drawerHeader: {
display: "flex",
alignItems: "center",
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: "flex-end"
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
marginLeft: -drawerWidth
},
contentShift: {
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
}),
marginLeft: 0
}
}));
export default function PersistentDrawerLeft() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(true);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<BrowserRouter>
<div className={classes.root}>
<CssBaseline />
<AppBar
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: open
})}
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Persistent drawer
</Typography>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<List>
<ListItem button key="home" to="/home" component={Link}>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
</List>
<Divider />
<List>
<ListItem button key="about" to="/about" component={Link}>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="About" />
</ListItem>
</List>
</Drawer>
<main
className={clsx(classes.content, {
[classes.contentShift]: open
})}
>
<div className={classes.drawerHeader} />
<Route path="/home" exact component={Home} />
<Route path="/about" component={About} />
</main>
</div>
</BrowserRouter>
);
}
Home.js
import React from "react";
const Home = () => {
return <h1>Home Page</h1>;
};
export default Home;
关于.js
import React from "react";
const About = () => {
return <h1>About Page</h1>;
};
export default About;
最佳答案
如果我正确理解您的问题,您正在尝试创建嵌套路由,即您希望在“/dashboard”子域中的嵌套路由上呈现 About
组件,例如“/dashboard”/关于”。
问题
您已将 AppDrawerBar
组件包装到第二个嵌套 Router 中。这可能会扰乱整个应用程序路由,因为包装应用程序的外部路由器不知道嵌套内部路由器正在处理的任何内容。它也不嵌套路由路径。
解决方案
创建一个新的
Dashboard
组件来充当“登陆”页面并管理嵌套路径。您还需要将AppDrawerBar
移至此处,因为它负责处理嵌套路线导航。import { Switch, Redirect, Route, useRouteMatch } from "react-router-dom"; import Home from "./Home"; import About from "./About"; import AppDrawerBar from "../components/AppDrawerBar"; const Dashboard = () => { const { path } = useRouteMatch(); return ( <> <AppDrawerBar> <Switch> <Route path={`${path}/about`} component={About} /> <Route path={`${path}/home`} exact component={Home} /> <Redirect to={`${path}/home`} /> </Switch> </AppDrawerBar> </> ); }; export default Dashboard;
不要用另一个
Router
包装AppDrawerBar
并删除其中定义的Route
组件。相反,渲染传递的子项。更新链接以使用当前路由匹配中的url
来计算嵌套链接。function PersistentDrawerLeft({ children }) { ... const { url } = useRouteMatch(); ... return ( <div className={classes.root} ... <Drawer className={classes.drawer} variant="persistent" anchor="left" open={open} classes={{ paper: classes.drawerPaper }} > <div className={classes.drawerHeader}> <IconButton onClick={handleDrawerClose}> {theme.direction === "ltr" ? ( <ChevronLeftIcon /> ) : ( <ChevronRightIcon /> )} </IconButton> </div> <Divider /> <List> <ListItem button key="home" to={`${url}/home`} component={Link}> ... </ListItem> </List> <Divider /> <List> <ListItem button key="about" to={`${url}/about`} component={Link}> ... </ListItem> </List> </Drawer> <main className={clsx(classes.content, { [classes.contentShift]: open })} > <div className={classes.drawerHeader} /> {children} </main> </div> ); }
演示
关于javascript - 在react-router-dom中分离路由的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67174959/