将React Router与物料ui集成不起作用 [英] Integrating react router with material ui is not working

查看:37
本文介绍了将React Router与物料ui集成不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在侧边栏菜单中将react-router与材质ui集成在一起,但是它不起作用.当我单击菜单项时,仅url发生更改,但组件未加载.我在[https://material-ui.com/guides/composition/#link]上的指南中进行了尝试,但是每次尝试更改代码中的内容时,都会得到奇怪的结果.我的应用程序组件如下,

layout.js

import React, {useCallback, useState} from 'react';从'clsx'导入clsx;进口 {转变,路线,BrowserRouter作为路由器}来自"react-router-dom";进口 {makeStyles,使用主题}来自"@ material-ui/core/styles";进口 {抽屉,CssBaseline,AppBar,工具栏IconButton,排版,分频器列表,}来自"@ material-ui/core";从'@ material-ui/icons/Menu'导入MenuIcon;从"./menu"导入{MenuItem};从"./menuitems"导入{menu};从"./DowTheory"导入{TheDowTheory};从"../Home/Home"导入{HomePage};const抽屉宽度= 280;const useStyles = makeStyles((theme)=>({根: {显示:"flex",},appBar:{zIndex:theme.zIndex.drawer + 1过渡:theme.transitions.create([''width','margin'],{缓动:theme.transitions.easing.sharp,持续时间:theme.transitions.duration.leavingScreen,}),},menuButton:{marginRight:36,},隐藏: {显示:无",},抽屉: {宽度:抽屉宽度,flexShrink:0,whiteSpace:"nowrap",},抽屉打开:{宽度:抽屉宽度,过渡:theme.transitions.create('width',{缓动:theme.transitions.easing.sharp,持续时间:theme.transitions.duration.enteringScreen,}),},抽屉关闭:{过渡:theme.transitions.create('width',{缓动:theme.transitions.easing.sharp,持续时间:theme.transitions.duration.leavingScreen,}),overflowX:隐藏",宽度:theme.spacing(7)+ 1[theme.breakpoints.up('sm')]:{宽度:theme.spacing(9)+ 1},},工具栏:{显示:"flex",alignItems:'中心',justifyContent:'flex-end',填充:theme.spacing(0, 1),//内容必须位于应用栏下方... theme.mixins.toolbar,},内容: {flexGrow:1填充:theme.spacing(3),},}));导出const MiniDrawer =()=>{const classes = useStyles();const theme = useTheme();const [open,setOpen] = useState(true);const toggle = useCallback(()=>setOpen(!open),[打开],);返回 (< div className = {classes.root}>< CssBaseline/>< AppBarposition ="fixed"className = {classes.appBar}样式= {{backgroundColor:'white'}}><工具栏>< IconButtoncolor =继承"aria-label =打开抽屉"onClick = {toggle}edge =开始"className = {clsx(classes.menuButton,{[classes.open] :! open,})}样式= {{颜色:'#10375c'}}>< MenuIcon/></IconButton><版式变体="h4".noWrap样式= {{颜色:'#10375c'}}>StockViz</Typography></工具栏></AppBar><抽屉变体=永久的".className = {clsx(classes.drawer,{[classes.drawerOpen]:打开,[classes.drawerClose]:!open,})}类别= {{论文:clsx({[classes.drawerOpen]:打开,[classes.drawerClose]:!open,}),}}>< div className = {classes.toolbar}>< IconButton onClick = {toggle}/></div><除法器/><列表>{menu.map((item,key)=>< MenuItem key = {key} item = {item}/>)}}</列表></抽屉>< main className = {classes.content}>< div className = {classes.toolbar}/><路由器>< Switch><路由精确路径='/'component = {HomePage}/><路由精确路径='/thedowtheory'组件= {TheDowTheory}/></Switch></路由器></main></div>);} 

menu.js

 从"react"导入React,{forwardRef,Fragment,useMemo,useState};从'@ material-ui/core/styles'导入{makeStyles};从'@ material-ui/core/List'导入列表;从'@ material-ui/core/ListItem'导入ListItem;从 '@material-ui/core/ListItemIcon' 导入 ListItemIcon;从'@ material-ui/core/ListItemText'导入ListItemText;从'@ material-ui/core/Collapse'导入折叠;从'@ material-ui/icons/ExpandLess'导入ExpandLess;从'@ material-ui/icons/ExpandMore'导入ExpandMore;从"./utils"导入{hasChildren};从"@ material-ui/core/Divider"导入除法器;进口 {关联,BrowserRouter作为路由器,}来自"react-router-dom";const useStyles = makeStyles((theme)=>({关联: {textDecoration:无",颜色:theme.palette.text.primary}}))const SingleLevel =({{item})=>{const classes = useStyles();返回 (<路由器><链接到= {item.to} className = {classes.link}>< ListItem按钮>< ListItemIcon> {item.icon}</ListItemIcon>< ListItemText primary = {item.title}/></ListItem></链接></路由器>);};const MultiLevel =({item})=>{const classes = useStyles();const {items:children} = item;const [open,setOpen] = useState(false);const handleClick =()=>{setOpen((prev)=>!prev);};返回 (<路由器><链接到= {item.to} className = {classes.link}>< ListItem按钮onClick = {handleClick}>< ListItemIcon> {item.icon}</ListItemIcon>< ListItemText primary = {item.title}/>{打开 ?< ExpandLess/>:< ExpandMore/>}</ListItem><折叠进入= {打开}超时=自动";unmountOnExit>< List component ='div'禁用填充>{children.map((child,key)=>(< MenuItem key = {key} item = {child}/>))}</列表></折叠></链接></路由器>);};export const MenuItem =({{item})=>{const Component = hasChildren(item)?多层:单层;返回<组件item = {item}/> ;;}; 

menuitems.js

 从"@ material-ui/icons/HomeOutlined"导入HomeOutlinedIcon;从"@ material-ui/icons/LocalLibraryOutlined"导入LocalLibraryOutlinedIcon;从"@ material-ui/icons/TrendingUpOutlined"导入TrendingUpOutlinedIcon;从"@ material-ui/icons/DescriptionOutlined"导入DescriptionOutlinedIcon;从反应"导入React;从"../Home/Home"导入{HomePage};从./DowTheory"导入{TheDowTheory};导出const菜单= [{图标:< HomeOutlinedIcon/> ;,标题:首页",至: '/',组件:首页,项目: []},{图标:< LocalLibraryOutlinedIcon/> ;,标题:教育",项目: [{标题:技术分析",项目: [{标题:简介",组件:技术",到:'/technical'},{标题:陶氏理论",组件:TheDowTheory,到:'/thedowtheory'},{标题:图表和图表模式",组件:图表",制成图表'},{标题:趋势与趋势"趋势线",组成部分:趋势",到:'/trendlines'},{标题:支持与支持"抵抗性',组件:支持",到:'/sandr'},]},{标题:基本面分析",项目: [{标题:简介",组件:技术",到:'/fundamental'},{标题:陶氏理论",组件:技术",到:'/thedowtheory'},{标题:图表和图表模式",组件:技术",制成图表'},{标题:趋势与趋势"趋势线",组件:技术",到:'/trendlines'},{标题:支持与支持"抵抗性',组件:技术",到:'/sandr'},]},{标题:艾略特波浪分析",项目: [{标题:简介",组件:技术",到:'/elliot'},{标题:陶氏理论",组件:技术",到:'/thedowtheory'},{标题:图表和图表模式",组件:技术",制成图表'},{标题:趋势与趋势"趋势线",到:'/trendlines'},{标题:支持与支持"抵抗性',到:'/sandr'},]},]},{图标:<TrendingUpOutlinedIcon/>,到:'/options',组件:选项",标题:选项"},{图标:< DescriptionOutlinedIcon/> ;,到:'/blog',组件:博客",标题:博客"},] 

utils.js

  import从"react"导入React;导出函数hasChildren(item){const {items:children} = item;如果(孩子===未定义){返回false;}如果(children.constructor!==数组){返回false;}如果(children.length === 0){返回false;}返回true;} 

解决方案

@Yogendra Kumar这个答案是这篇

@Yogendra Kumar,此解决方案未考虑 menu.js 中的 component 属性.

I am trying to integrate react-router with material ui in sidebar menu, but it is not working. When I click on the menu item, only url changes but component doesn't load. I tried it with the guide on [https://material-ui.com/guides/composition/#link], but getting weird results everytime I try to change something in the code. My app components are as below,

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>
  );
}

menu.js

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} />;
};

menuitems.js

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'
  },
]

utils.js

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;
}

解决方案

@Yogendra Kumar This answer is a continuation from this post. I will use the same code with enhancement to add support for React Router.


First, I would change my SingleLevel component to use Link component from react-router-dom. This can be done by passing component={Link} to ListItem. It's also worth noting that if the current item has no to property, I would like the user to be redirected to 404 page.

Read the guides on integrating react-router-dom to material-ui here.

import { Link } from "react-router-dom";
...

const SingleLevel = ({ item }) => {
  return (
    <ListItem button component={Link} to={item.to || "/404"}>
      <ListItemIcon>{item.icon}</ListItemIcon>
      <ListItemText primary={item.title} />
    </ListItem>
  );
};

This changes is not needed for MultiLevel's ListItem component, because we don't want to link user to a page when its item is clicked — but show its collapsed items only.

Next, I would create a Routes component that will have all of my route configurations.

react-router-dom docs

Routes.js

export default function Routes() {
  return (
    <Switch>
      <Route exact path="/" component={HomePage} />
      <Route path="/thedowtheory" component={TheDowTheory} />
      <Route path="/trendlines" component={TrendLines} />
      <Route path="/sandr" component={SandR} />
      <Route path="/chart" component={Chart} />

      <Route path="/404" component={NotFound} />
      <Redirect to="/404" />
    </Switch>
  );
}

Lastly, I will rename the App.js file to Nav.js because I wan't App.js to have these codes instead

import { BrowserRouter as Router } from "react-router-dom";

import Nav from "./Nav";
import Routes from "./Routes";

export default function App() {
  return (
    <React.Fragment>
      <Router>
        <Nav />
        <Routes />
      </Router>
    </React.Fragment>
  );
}

@Yogendra Kumar, this solution doesn't take account the component property from menu.js.

这篇关于将React Router与物料ui集成不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆