【问题标题】:React Router with Material UI使用 Material UI 反应路由器
【发布时间】:2020-08-12 05:26:25
【问题描述】:

我对 react 还很陌生,现在我正在尝试将 React Router 和 Material UI 一起使用。

我的布局文件使用 Material UI 中的导航抽屉,我将菜单放在左侧,内容放在右侧,如下图所示

我想要做的是,当我点击Test Comp时,它应该加载右侧的TestComp.js组件,以此类推Test Comp One加载TestCompOne.js。

我已经通过了带有 Links、Switch 和 Route 的 ReactRouter 代码,但我不确定将它们放置在哪里。

我尝试为应该有路由器的布局文件添加以下代码,但我确信我没有做对 我得到的错误是

Error: Invariant failed: You should not use <Link> outside a <Router>

能否请您纠正我的问题

index.js

import Layout from './Layout/Layout'

ReactDOM.render(
  <React.StrictMode>
    <Layout/>
  </React.StrictMode>,
  document.getElementById('root')
);

组件 - TestComp.js

import React from "react"

export default class TestComp extends React.Component {
    render() {
        return (
            <h1>test component for test</h1>
        );
    }
}

组件 TestCompOne.js

import React from "react"

export default class TestCompOne extends React.Component {
    render() {
        return (
            <h1>test component ONE for test</h1>
        );
    }
}

我正在粘贴整个布局文件,它有点大,但主要区域是drawer,它是左侧菜单,要显示的内容是我添加&lt;Router&gt; 的位置。 抱歉,如果这是完全错误的做法,请提出建议

Component Layout.js - 具有来自 Material UI 的导航抽屉,我想在其中添加路由器以打开单个组件

import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '@material-ui/core/AppBar';
import CssBaseline from '@material-ui/core/CssBaseline';
import Divider from '@material-ui/core/Divider';
import Drawer from '@material-ui/core/Drawer';
import Hidden from '@material-ui/core/Hidden';
import IconButton from '@material-ui/core/IconButton';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import MailIcon from '@material-ui/icons/Mail';
import MenuIcon from '@material-ui/icons/Menu';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import { MenuItem, MenuList } from '@material-ui/core';
import TestComp from '../Components/TestComp'
import TestCompOne from '../Components/TestCompOne'
import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link
  } from "react-router-dom";

const drawerWidth = 240;

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
  },
  drawer: {
    [theme.breakpoints.up('sm')]: {
      width: drawerWidth,
      flexShrink: 0,
    },
  },
  appBar: {
    [theme.breakpoints.up('sm')]: {
      width: `calc(100% - ${drawerWidth}px)`,
      marginLeft: drawerWidth,
    },
  },
  menuButton: {
    marginRight: theme.spacing(2),
    [theme.breakpoints.up('sm')]: {
      display: 'none',
    },
  },
  // necessary for content to be below app bar
  toolbar: theme.mixins.toolbar,
  drawerPaper: {
    width: drawerWidth,
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3),
  },
}));

function ResponsiveDrawer(props) {
  const { container } = props;
  const classes = useStyles();
  const theme = useTheme();
  const [mobileOpen, setMobileOpen] = React.useState(false);
  const [sampleText, setSampleText] = React.useState("test");

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

  const testCompClicked = () => {
    setSampleText("Test Comp")
  };

  const testCompOneClicked = () => {
    setSampleText("Test Comp One")
  };

  const drawer = (
    <div>
      <div className={classes.toolbar} />
      <Divider />
      <MenuList>
        <MenuItem onClick={testCompClicked} component={Link} to="/testcomp">
          <ListItemIcon>
            <InboxIcon />
          </ListItemIcon>
          <ListItemText primary="Test Comp" />
        </MenuItem>
        <MenuItem onClick={testCompOneClicked} component={Link} to="/testcompone">
          <ListItemIcon>
            <MailIcon />
          </ListItemIcon>
          <ListItemText primary="Test Comp One" />
        </MenuItem>
      </MenuList>
      <Divider />
    </div>
  );

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar position="fixed" className={classes.appBar} style={{ background: '#78a02e'}}>
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            edge="start"
            onClick={handleDrawerToggle}
            className={classes.menuButton}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            Responsive drawer
          </Typography>
        </Toolbar>
      </AppBar>
      <nav className={classes.drawer} aria-label="mailbox folders">
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
      <main className={classes.content}>
        <div className={classes.toolbar} />
        <h1>{sampleText}</h1>
        <h3>I want to show individual components using React Rounter when I press them from the left menu</h3>
        <Router>
            <Switch>
            <Route path="/testcomp">
                <TestComp />
            </Route>
            <Route path="/testcompone">
                <TestCompOne />
            </Route>
            <Route path="/">
                <TestComp />
            </Route>
            </Switch>
        </Router>
      </main>
    </div>
  );
}

ResponsiveDrawer.propTypes = {
  /**
   * Injected by the documentation to work in an iframe.
   * You won't need it on your project.
   */
  container: PropTypes.any,
};

export default ResponsiveDrawer;

【问题讨论】:

  • 您还需要将链接放在Router 内
  • 正如上面的评论所说,您可能希望将&lt;Router /&gt; 作为顶级父级放在外面
  • 那么菜单项的点击量呢?

标签: javascript reactjs react-router material-ui


【解决方案1】:

Links 需要在 &lt;Router&gt; 环境中。 试试

  return (
    <Router>
    <div className={classes.root}>
      <CssBaseline />
      <AppBar position="fixed" className={classes.appBar} style={{ background: '#78a02e'}}>
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            edge="start"
            onClick={handleDrawerToggle}
            className={classes.menuButton}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            Responsive drawer
          </Typography>
        </Toolbar>
      </AppBar>
      <nav className={classes.drawer} aria-label="mailbox folders">
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
      <main className={classes.content}>
        <div className={classes.toolbar} />
        <h1>{sampleText}</h1>
        <h3>I want to show individual components using React Rounter when I press them from the left menu</h3>
            <Switch>
            <Route path="/testcomp">
                <TestComp />
            </Route>
            <Route path="/testcompone">
                <TestCompOne />
            </Route>
            <Route path="/">
                <TestComp />
            </Route>
            </Switch>
          </main>
        </div>
    </Router>
  );

【讨论】:

    猜你喜欢
    • 2017-05-29
    • 2018-04-04
    • 2022-01-15
    • 1970-01-01
    • 2017-10-26
    • 2020-02-16
    • 2021-10-15
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多