Reactjs 将react router与物料ui集成不起作用

Reactjs 将react router与物料ui集成不起作用,reactjs,react-router,material-ui,Reactjs,React Router,Material Ui,我试图将react router与侧边栏菜单中的材质ui集成,但它不起作用。当我点击菜单项时,只有url会改变,但组件不会加载。我戴着导游试过了[https://material-ui.com/guides/composition/#link],但每次我试图更改代码时都会得到奇怪的结果。我的应用程序组件如下所示 layout.js import React, {useCallback, useState} from 'react'; import clsx from 'clsx'; import

我试图将react router与侧边栏菜单中的材质ui集成,但它不起作用。当我点击菜单项时,只有url会改变,但组件不会加载。我戴着导游试过了[https://material-ui.com/guides/composition/#link],但每次我试图更改代码时都会得到奇怪的结果。我的应用程序组件如下所示

layout.js

import React, {useCallback, useState} from 'react';
import clsx from 'clsx';
import {
  Switch,
  Route,
  BrowserRouter as Router
}from 'react-router-dom';
import {
  makeStyles,
  useTheme
} from '@material-ui/core/styles';
import {
  Drawer,
  CssBaseline,
  AppBar,
  Toolbar,
  IconButton,
  Typography,
  Divider,
  List,
} from '@material-ui/core';
import MenuIcon from '@material-ui/icons/Menu';
import {MenuItem} from "./menu";
import {menu} from "./menuitems";
import {TheDowTheory} from "./DowTheory";
import {HomePage} from "../Home/Home";



const drawerWidth = 280;

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
  },
  menuButton: {
    marginRight: 36,
  },
  hide: {
    display: 'none',
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0,
    whiteSpace: 'nowrap',
  },
  drawerOpen: {
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  drawerClose: {
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    overflowX: 'hidden',
    width: theme.spacing(7) + 1,
    [theme.breakpoints.up('sm')]: {
      width: theme.spacing(9) + 1,
    },
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3),
  },
}));

export const MiniDrawer = () => {
  const classes = useStyles();
  const theme = useTheme();
  const [open, setOpen] = useState(true);

  const toggle = useCallback(
    () => setOpen(!open),
    [open],
  );

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar
        position="fixed"
        className={classes.appBar}
        style={{backgroundColor:'white'}}
      >
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={toggle}
            edge="start"
            className={clsx(classes.menuButton, {
              [classes.open]: !open,
            })}
            style={{color:'#10375c'}}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h4"
                      noWrap
                      style={{color:'#10375c'}}
          >
            StockViz
          </Typography>
        </Toolbar>
      </AppBar>
      <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={toggle} />
        </div>
        <Divider />
        <List>
          {menu.map((item, key) => <MenuItem key={key} item={item} />)}
        </List>
      </Drawer>
      <main className={classes.content}>
        <div className={classes.toolbar} />
          <Router>
            <Switch>
              <Route exact path='/' component={HomePage} />
              <Route exact path='/thedowtheory' component={TheDowTheory} />
            </Switch>
          </Router>
      </main>
    </div>
  );
}

组件
菜单
必须位于
路由器
内,如果您想直接指向另一个组件。

@Yogendra Kumar此答案是此答案的延续。我将使用相同的增强代码来添加对React路由器的支持


首先,我将把
SingleLevel
组件从
react-router-dom
更改为使用
Link
组件。这可以通过将
component={Link}
传递到
ListItem
来完成。还值得注意的是,如果当前项目没有
to
属性,我希望用户被重定向到404页面

阅读有关集成
路由器dom
材质ui
的指南

从“react router dom”导入{Link};
...
常量单级=({item})=>{
返回(
{item.icon}
);
};
对于
multivel
ListItem
组件,不需要进行此更改,因为我们不希望在单击其项目时将用户链接到页面,而只显示其折叠的项目

接下来,我将创建一个
路由
组件,该组件将包含我的所有路由配置

react路由器dom

Routes.js

导出默认函数路由(){
返回(
);
}
最后,我将把
App.js
文件重命名为
Nav.js
,因为我不想用
App.js
来代替这些代码

从“react Router dom”导入{BrowserRouter as Router};
从“/Nav”导入Nav;
从“/Routes”导入路由;
导出默认函数App(){
返回(
);
}


@Yogendra Kumar,此解决方案不考虑文件
layout.js
menu.js

哪个菜单组件的
component
属性。将标签
Router
作为此组件的父标签移出。您可以将代码放在codepen.io上吗。所以我们可以看看这个。您的菜单项上是否需要有
component
属性?我看到了家庭的
组件:主页
。我把它放在编程的路径上。目前我没有使用它
import React, {forwardRef, Fragment, useMemo, useState} from 'react';
import { makeStyles } from '@material-ui/core/styles';
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 Collapse from '@material-ui/core/Collapse';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import {hasChildren} from "./utils";
import Divider from "@material-ui/core/Divider";
import {
  Link,
  BrowserRouter as Router,
} from "react-router-dom";

const useStyles = makeStyles((theme) => ({
  link: {
    textDecoration: 'none',
    color: theme.palette.text.primary
  }
}))


const SingleLevel = ({ item }) => {
  const classes = useStyles();
  return (
    <Router>
      <Link to={item.to} className={classes.link}>
        <ListItem button>
          <ListItemIcon>{item.icon}</ListItemIcon>
          <ListItemText primary={item.title} />
        </ListItem>
      </Link>
    </Router>
  );
};

const MultiLevel = ({ item }) => {
  const classes = useStyles();
  const { items: children } = item;
  const [open, setOpen] = useState(false);

  const handleClick = () => {
    setOpen((prev) => !prev);
  };

  return (
    <Router>
      <Link to={item.to} className={classes.link}>
        <ListItem button onClick={handleClick}>
        <ListItemIcon>{item.icon}</ListItemIcon>
        <ListItemText primary={item.title} />
        {open ? <ExpandLess /> : <ExpandMore />}
      </ListItem>
      <Collapse in={open} timeout="auto" unmountOnExit>
        <List component='div'
              disablePadding
        >
                {children.map((child, key) => (
                        <MenuItem key={key} item={child} />
                ))}
        </List>
      </Collapse>
      </Link>
    </Router>
  );
};

export const MenuItem = ({ item }) => {
  const Component = hasChildren(item) ? MultiLevel : SingleLevel;
  return <Component item={item} />;
};
import HomeOutlinedIcon from "@material-ui/icons/HomeOutlined";
import LocalLibraryOutlinedIcon from "@material-ui/icons/LocalLibraryOutlined";
import TrendingUpOutlinedIcon from "@material-ui/icons/TrendingUpOutlined";
import DescriptionOutlinedIcon from "@material-ui/icons/DescriptionOutlined";
import React from "react";
import {HomePage} from "../Home/Home";
import {TheDowTheory} from "./DowTheory";


export const menu = [
  {
    icon: <HomeOutlinedIcon/>,
    title: 'Home',
    to: '/',
    component: HomePage,
    items: []
  },
  {
    icon: <LocalLibraryOutlinedIcon/>,
    title: 'Education',
    items: [
      {
        title:'Technical Analysis',
        items: [
          {
            title: 'Introduction',
            component: 'Technical',
            to: '/technical'
          },
          {
            title: 'The Dow Theory',
            component: TheDowTheory,
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            component: 'Charts',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            component: 'Trends',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            component: 'Support',
            to: '/sandr'
          },
        ]
      },
      {
        title:'Fundamental Analysis',
        items: [
          {
            title: 'Introduction',
            component: 'Technical',
            to: '/fundamental'
          },
          {
            title: 'The Dow Theory',
            component: 'Technical',
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            component: 'Technical',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            component: 'Technical',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            component: 'Technical',
            to: '/sandr'
          },
        ]
      },
      {
        title:'Elliot Wave Analysis',
        items: [
          {
            title: 'Introduction',
            component: 'Technical',
            to: '/elliot'
          },
          {
            title: 'The Dow Theory',
            component: 'Technical',
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            component: 'Technical',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            to: '/sandr'
          },
        ]
      },
      ]
  },
  {
    icon: <TrendingUpOutlinedIcon/>,
    to: '/options',
    component: 'Options',
    title: 'Options'
  },
  {
    icon: <DescriptionOutlinedIcon/>,
    to: '/blog',
    component: 'Blog',
    title: 'Blog'
  },
]
import React from "react";

export function hasChildren(item) {
  const { items: children } = item;

  if (children === undefined) {
    return false;
  }

  if (children.constructor !== Array) {
    return false;
  }

  if (children.length === 0) {
    return false;
  }

  return true;
}