如何在 React 中正确使用路由器内部的路由器

Posted

技术标签:

【中文标题】如何在 React 中正确使用路由器内部的路由器【英文标题】:How to properly use Router inside Router in React 【发布时间】:2021-07-06 14:28:03 【问题描述】:

我正在努力使用“react-router-dom”创建路由。 正在显示默认的“Page1”: as you can see here, 但是切换到“Page2”或“Page3”时出现空白页。

如果有人能够查看我的代码,我会很高兴。谢谢!

App.js:

import Layout from "./Layout";
import Login from "./Login";
import  BrowserRouter as Router, Switch, Route  from "react-router-dom";

function App() 
  return (
    <Router>
      <Switch>
        <Route exact path="/" component=Layout />
        <Route path="/login" component=Login />
      </Switch>
    </Router>
  );


export default App;   

登录.js:

import React from "react";
import  makeStyles  from "@material-ui/core/styles";

const useStyles = makeStyles(() => (
  root: 
    flexGrow: "1",
    height: "100%",
  ,
));

const Login = () => 
  const classes = useStyles();
  return <div className=classes.root>Login</div>;
;

export default Login;

Layout.js:

import React from "react";
import  makeStyles  from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Header from "./Header";
import Menu from "./Menu";
import Page1 from "./Page1";
import Page2 from "./Page2";
import Page3 from "./Page3";
import  Switch, Route  from "react-router-dom";

const useStyles = makeStyles(() => (
  root: 
    display: "flex",
    overflow: "hidden",
    backgroundColor: "red",
  ,
));

export default function Layout() 
  const classes = useStyles();

  return (
    <div className=classes.root>
      <Menu />
      <Grid container direction="column">
        <Grid item xs>
          <Header />
        </Grid>
        <Grid item xs>
          <Switch>
            <Route exact path="/" component=Page1 />
            <Route path="/page2" component=Page2 />
            <Route path="/page3" component=Page3 />
          </Switch>
        </Grid>
      </Grid>
    </div>
  );


菜单.js

import  useHistory  from "react-router-dom";
import React,  useState  from "react";
import  makeStyles, withStyles  from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";

const useStyles = makeStyles((theme) => (
  root: 
    height: "100vh",
    width: "90px",
    backgroundColor: theme.palette.background.menu,
    textAlign: "center",
    justifyContent: "center",
    backgroundColor: "lightblue",
  ,
));

const StyledListItem = withStyles((theme) => (
  root: 
    flexDirection: "column",
    textAlign: "center",
    opacity: 0.8,
  ,
))(ListItem);

const MainNavMenu = (props) => 
  const [selectedIndex, setSelectedIndex] = useState(0);
  const classes = useStyles(props);
  let history = useHistory();

  // Navigate between pages
  const navigate = (text, index) => 
    setSelectedIndex(index);
    if ("page1" === text) 
      history.push("/");
     else if ("page2" === text) 
      history.push("/page2");
     else 
      history.push("/page3");
    
  ;

  return (
    <div className=classes.root>
      <List>
        ["page1", "page2", "page3"].map((text, index) => (
          <StyledListItem
            button
            key=index
            selected=selectedIndex === index
            onClick=() => 
              navigate(text, index);
            
          >
            <ListItemText primary=text />
          </StyledListItem>
        ))
      </List>
    </div>
  );
;

export default MainNavMenu;

Page1.js(所有页面看起来都一样):

function Page1() 
  return (
    <div>
      <h1>Page 1</h1>
    </div>
  );


export default Page1;

【问题讨论】:

【参考方案1】:

您的应用需要知道它应该通过Layout 组件处理/page2/page1。现在不是因为你的Route 只匹配exact path="/"

您可以删除exact 以通过Layout 发送所有流量。由于使用了第一个匹配项,因此您总是希望将您的 Route 组件从最具体到最不具体列出。如果没有exactLayoutRoute 现在属于列表底部。

function App() 
  return (
    <Router>
      <Switch>
        <Route path="/login" component=Login />
        <Route path="/" component=Layout />
      </Switch>
    </Router>
  );


Layout 中的路径与 Menu 中的路径不匹配。 Layout 中没有 /page3

布局:

<Route exact path="/" component=Page1 />
<Route path="/page1" component=Page2 />
<Route path="/page2" component=Page3 />

菜单:

["page1", "page2", "page3"].map((text, index) => (

您可能想像这样更改Layout

<Route exact path="/" component=Page1 />
<Route path="/page2" component=Page2 />
<Route path="/page3" component=Page3 />

我个人会使用 react-router-dom Link 组件进行导航,但您需要以不同的方式处理样式。

【讨论】:

谢谢!我删除了确切的路径并将默认路径移动到底部并且它起作用了!【参考方案2】:

您的代码中没有 page1 或 page2 路由。这就是你得到一个空白页的原因。

【讨论】:

我忘记添加 Menu.js 代码并更新了 Layout.js 中的路径,但仍然无法正常工作 您需要在路径名前加上“/”。喜欢path="/page1"【参考方案3】:

删除应用组件中的exact。由于您放置exact,它不会切换到嵌套组件。

<Switch>
      <Route path="/" component=Layout />
      <Route path="/login" component=Login />
</Switch>

编辑评论

只需命名路线而不是空白,例如“/home”并将空白路线重定向到家。 像这样

<Switch>
      <Route exact path="/" > <Redirect to="/home" /> </Route>
      <Route path="/home" component=Layout />
      <Route path="/login" component=Login />
</Switch>

大多数情况下 page1,page2,page3 都可以使用。如果没有,实现“useRoutematch”并将路径放在Layout.js中的&lt;Route&gt;

【讨论】:

现在我可以在“/page1”、“/page2”和“/page3”之间导航,但是当我导航到“/login”(通过更改网址)时,不会显示登录屏幕。相反,我看到 Layout.js 没有页面【参考方案4】:
 import  BrowserRouter as Router, Route, Switch  from 'react-router-dom';
 import React,  Fragment, useEffect  from 'react';
  <Router>
    <Fragment>
      <Navbar />
      <Switch>
        <Route exact path="/" component=Landing />
        <Route component=Routes />
      </Switch>
    </Fragment>
  </Router>

【讨论】:

以上是关于如何在 React 中正确使用路由器内部的路由器的主要内容,如果未能解决你的问题,请参考以下文章

如何在页面打开后从 cookie 中正确设置属性(如果用户已登录)或使用路由器和 redux 在 React 中使用 F5

如何在我的 React SPA 中访问路由组件,同时保持正确的 CSP?

我怎么知道我是否在React路由器内部?

如何在使用 Passport 进行社交身份验证后重定向到正确的客户端路由(react、react-router、express、passport)

无法在 React 路由器中正确地为路径添加前缀

如何用react-router做网易云音乐的路由切换