Why does React Router Change URL but doesn't Change the View - javascript

I have created a react 16.8 application and am using react-router-dom. I built the Navigation Bar with React Semantic UI library. My Problem is that when I click the Menu Item Navlink the App changes the url however, it does not rerender the app with the new component that matches the path. I have tried various fixes to no avail. I have used Switch I have used Navlink, I have used withRouter. I tried to do a componentDidUnmount. When I refresh the app the component I am looking for does work. It just doesnt change when I click the navigation link. Here is my code. I am only asking because I have no other option and all the other answers are so outdated.
The App.js
import React from 'react';
import {BrowserRouter, Route, withRouter, Switch} from 'react-router-dom'
import Landing from './components/Landing/Landing'
import Sales from './components/Dashboard/Sales/Sales'
import Orders from './components/Dashboard/Orders/Orders'
import Returns from './components/Dashboard/Returns/Returns'
import DailySales from './components/Reports/Sales/DailySales/DailySales';
function App() {
return (
<BrowserRouter>
<div className='App'>
<Switch>
<Route path="/" exact component={withRouter(Landing)} />
<Route path="/dashboards/sales" exact component={withRouter(Sales)} />
<Route path="/dashboards/orders" exact component={withRouter(Orders)} />
<Route path="/dashboards/returns" component={withRouter(Returns)} />
<Route path="/reports/dailysales/" component={withRouter(DailySales)} />
</Switch>
</div>
</BrowserRouter>
);
}
export default App;
And the Navigation component
import React from 'react'
import logo_icon from '../../../../assets/images/logo_icon.png'
import { Dropdown , Menu, Image } from 'semantic-ui-react'
import { BrowserRouter, Route ,Link, NavLink , withRouter ,Switch} from 'react-router-dom'
import Landing from '../../../Landing/Landing'
import Sales from '../../../Dashboard/Sales/Sales'
const Navigation = () => (
<BrowserRouter>
<Menu className="ui secondary">
{/* Menu Icon */}
<Link to="/dashboards/sales">
<Dropdown.Item>
<Image className="item headLogo" src={logo_icon} />
</Dropdown.Item>
</Link>
{/* End of Menu Icon */}
{/* Here is Sales Dropdown */}
<Dropdown className="ui dropdown item" text="Sales" icon="dropdown">
<Dropdown.Menu>
<Menu.Item className="item" as={ NavLink } exact to="/dashboards/sales" name="Dashboard" />
<Dropdown className="ui dropdown link item" text="Reports">
<Dropdown.Menu>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/sales" name="Daily Sales"/>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/sales" name="Sales Summary"/>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/sales" name="Profit Margin"/>
</Dropdown.Menu>
</Dropdown>
</Dropdown.Menu>
</Dropdown>
{/* End of Sales Dropdown */}
{/* Here is Customer Service Dropdown */}
<Dropdown className="ui dropdown item" text="Customer Service">
<Dropdown.Menu>
<Dropdown className="ui dropdown link item" text="Reports">
<Dropdown.Menu>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Service Level(Voice)"/>
</Dropdown.Menu>
</Dropdown>
</Dropdown.Menu>
</Dropdown>
{/* End of Customer Service Dropdown */}
{/* Here is Order Management Dropdown */}
<Dropdown className="ui dropdown item" text="Order Management">
<Dropdown.Menu>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Dashboard"/>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Fishbowl Anywhere"/>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Search Orders"/>
</Dropdown.Menu>
</Dropdown>
{/*End of Order Management Dropdown */}
{/*Here is Inventory Management Dropdown */}
<Dropdown className="ui dropdown item" text="Inventory Management">
<Dropdown.Menu>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="View Inventory"/>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Monitor Inventory"/>
</Dropdown.Menu>
</Dropdown>
{/*End of Inventory Management Dropdown */}
{/*Here is Returns Dropdown */}
<Dropdown className="ui dropdown item" text="Returns" icon="dropdown">
<Dropdown.Menu>
<Menu.Item className="item" as={ Link } to="/dashboards/orders" name="Dashboard" />
<Menu.Item className="item" as={ Link } to="/dashboards/orders" name="Search Returns" />
<Dropdown className="ui dropdown link item" text="Reports">
<Dropdown.Menu>
<Menu.Item className="ui dropdown link item" as={ Link } to="/dashboards/orders" name="Weekly Returns"/>
</Dropdown.Menu>
</Dropdown>
</Dropdown.Menu>
</Dropdown>
{/*End of returns Dropdown */}
</Menu>
</BrowserRouter>
)
export default withRouter(Navigation);

Try taking BrowserRouter off of your Navigation component

Related

Ant design - custom spacing between menu item

I have a Menu Component
As you can see, there are two problems on the Menu Component
1. The padding-left and padding-right(red arrows) are not the same
2. The spacing between MenuItem(blue arrows) is not the same.
How can I update the styles to fix above problems?
demo.js
import React from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Menu } from "antd";
import {
MailOutlined,
AppstoreOutlined,
SettingOutlined
} from "#ant-design/icons";
const App = () => (
<Menu
mode="horizontal"
defaultSelectedKeys={["mail"]}
style={{ border: "1px solid grey", justifyContent: "space-between" }}
>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.SubMenu
key="SubMenu"
title="Navigation Two - Submenu"
icon={<SettingOutlined />}
>
<Menu.Item key="two" icon={<AppstoreOutlined />}>
Navigation Two
</Menu.Item>
<Menu.Item key="three" icon={<AppstoreOutlined />}>
Navigation Three
</Menu.Item>
<Menu.ItemGroup title="Item Group">
<Menu.Item key="four" icon={<AppstoreOutlined />}>
Navigation Four
</Menu.Item>
<Menu.Item key="five" icon={<AppstoreOutlined />}>
Navigation Five
</Menu.Item>
</Menu.ItemGroup>
</Menu.SubMenu>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation Six
</Menu.Item>
</Menu>
);
export default App;
CodeSandbox
https://codesandbox.io/s/basic-usage-deprecated-syntactic-sugar-antd-4-22-4-forked-m4p6vh
you can put all menu options in one nav tag, and add menubar class to it.
CSS
.menubar {
/*current style properties + */
display: flex;
justify-content: space-between;
align-items: center;
}
My suggestion would be, that you should use Flex for aligning the UI. Flex will work in any size of screen size. And moreover coming to your problem, it can be solved by the below example
.yourClassName{
display:flex;
justify-content:'space-evenly'
};
Space evenly will add space to all elements in the class regardless of their size
I'm not sure if you want to spread it across the entire width but a nice solution is to put it between <Space></Space> (have a look here: https://ant.design/components/space/):
<Space>
<Menu
mode="horizontal"
defaultSelectedKeys={["mail"]}
style={{ border: "1px solid grey", justifyContent: "space-between" }}
>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.SubMenu
key="SubMenu"
title="Navigation Two - Submenu"
icon={<SettingOutlined />}
>
<Menu.Item key="two" icon={<AppstoreOutlined />}>
Navigation Two
</Menu.Item>
<Menu.Item key="three" icon={<AppstoreOutlined />}>
Navigation Three
</Menu.Item>
<Menu.ItemGroup title="Item Group">
<Menu.Item key="four" icon={<AppstoreOutlined />}>
Navigation Four
</Menu.Item>
<Menu.Item key="five" icon={<AppstoreOutlined />}>
Navigation Five
</Menu.Item>
</Menu.ItemGroup>
</Menu.SubMenu>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation Six
</Menu.Item>
</Menu>
</Space>

Open link when button is pressed

I have these buttons to which I would like to add link for redirect:
<Tooltip title="Open New Ticket">
<IconButton aria-label="filter list">
<AddTwoToneIcon />
</IconButton>
</Tooltip>
I added this:
<Tooltip title="Open New Ticket">
<Link to='open-ticket'>
<IconButton aria-label="filter list">
<AddTwoToneIcon />
</IconButton>
</Link>
</Tooltip>
But when I press the button I'm not redirected to a new page. This button for example is working fine:
<Link to='open-ticket'>
<Button
variant="contained"
color="primary"
size="small"
startIcon={<SaveIcon />}
>
Open Ticket
</Button>
</Link>
Do you know what is the proper way to implement this functionality?
Make sure you have installed react-router-dom. #material-ui/core/Link will not work.
Import BrowserRouter from react-router-dom and wrap your root component within.
import { BrowserRouter } from "react-router-dom"
import Root from "./views/Routes";
...
const App = props => {
return (
<BrowserRouter>
<Root />
</BrowserRouter>
);
}
In your Root component, specify the Routes with path and render component and wrap them inside Switch component. Switch enforces that only one of the Route children are matched. The URL is evaluated against Route components inside Switch and the first Route component whose path is a prefix-match of URL, is rendered. That is why you have to be careful of the order of Route components inside Switch
import { Fragment } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import Main from "./Main";
import Home from "./Home";
import About from "./About";
import NotFound from "./404";
const Root = (props) => {
return (
<Fragment>
<Main />
<Switch>
<Route path="/about" render={(p) => <About {...p} />} />
<Route path="/404" render={(p) => <NotFound {...p} />} />
<Route path="/" render={(p) => <Home {...p} />} />
<Redirect to="/404" />
</Switch>
</Fragment>
);
};
export default Root;
Use Link from react-router-dom
import { Link } from "react-router-dom";
import { Tooltip, IconButton, Grid } from "#material-ui/core";
import { HomeTwoTone, InfoTwoTone } from "#material-ui/icons";
const Main = (props) => {
return (
<Grid container spacing={2} justifyContent="center">
<Grid item>
<Tooltip title="Home Page">
<Link to="/">
<IconButton aria-label="filter list">
<HomeTwoTone />
</IconButton>
</Link>
</Tooltip>
</Grid>
<Grid item>
<Tooltip title="About Page">
<Link to="/about">
<IconButton aria-label="filter list">
<InfoTwoTone />
</IconButton>
</Link>
</Tooltip>
</Grid>
</Grid>
);
};
export default Main;
Here is a working demo
Inside your button you can add:
onClick={event => window.location.href='/your-href'}

React/Material UI Drawer With Nested List Items Closes on Click

I am using Material-UI for my React project and having issues with getting the drawer to function properly when I add in nested list items. Everything was working great until I added those in. I believe the root cause is that by clicking on the dropdown menu and changing the state of the list item to be open I'm causing the application to re-render. Not sure how to solve this.
Problem: Nested list items close the drawer automatically when you click the top level. The user then has to open the drawer again to see the list items in the drop down.
Desired Functionality: The user clicks the menu item to open the drawer. The user can click on "Leadership Triad" and see the menu items within while the drawer stays open. When the user clicks off, the drawer closes.
Code Sandbox
https://codesandbox.io/s/material-ui-nested-menu-forked-qqdiv
My Code
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import Drawer from "#material-ui/core/Drawer";
import List from "#material-ui/core/List";
import Divider from "#material-ui/core/Divider";
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 HomeIcon from "#material-ui/icons/Home";
import AccountCircle from "#material-ui/icons/AccountCircle";
import ExitToAppIcon from "#material-ui/icons/ExitToApp";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import PeopleIcon from "#material-ui/icons/People";
import BusinessIcon from "#material-ui/icons/Business";
import Menu from "#material-ui/core/Menu";
import MenuItem from "#material-ui/core/MenuItem";
import { Link as RouterLink } from "react-router-dom";
import Collapse from "#material-ui/core/Collapse";
const useStyles = makeStyles(theme => ({
root: { flexGrow: 1 },
menuButton: { marginRight: theme.spacing(2) },
title: { flexGrow: 1 },
list: { width: 250 },
nested: { paddingLeft: theme.spacing(4) },
}));
const Header = () => {
const [drawerOpen, setDrawerOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const [leadershipTriadMenuOpen, setLeadershipTriadMenuOpen] = useState(false);
const handleLeadershipTriadClick = () => {
setLeadershipTriadMenuOpen(!leadershipTriadMenuOpen);
};
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const toggleDrawer = () => {
setDrawerOpen(!drawerOpen);
};
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
onClick={() => toggleDrawer()}
>
<MenuIcon />
<Drawer
anchor="left"
open={drawerOpen}
onClose={() => toggleDrawer()}
>
<div className={classes.list}>
<List>
<ListItem button component={RouterLink} to="/">
<ListItemIcon>
<HomeIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
<ListItem
button
onClick={() => handleLeadershipTriadClick()}
>
<ListItemIcon>
<HomeIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Leadership Triad" />
{leadershipTriadMenuOpen ? (
<ExpandLess />
) : (
<ExpandMore />
)}
</ListItem>
<Collapse
in={leadershipTriadMenuOpen}
timeout="auto"
unmountOnExit
>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
</ListItem>
</List>
</Collapse>
<ListItem button>
<ListItemIcon>
<InboxIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Testing" />
</ListItem>
<ListItem button>
<ListItemIcon>
<InboxIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Testing" />
</ListItem>
</List>
<Divider />
<List>
<ListItem
button
component={RouterLink}
to="/admin/companies"
>
<ListItemIcon>
<BusinessIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Companies" />
</ListItem>
<ListItem
button
component={RouterLink}
to="/admin/users"
>
<ListItemIcon>
<PeopleIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Users" />
</ListItem>
</List>
<Divider />
<List>
<ListItem button component={RouterLink} to="/profile">
<ListItemIcon>
<AccountCircle color="primary" />
</ListItemIcon>
<ListItemText primary="Profile" />
</ListItem>
<ListItem button component={RouterLink} to="/logout">
<ListItemIcon>
<ExitToAppIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Logout" />
</ListItem>
</List>
</div>
</Drawer>
</IconButton>
<Typography variant="h6" className={classes.title}>
Leadership Program
</Typography>
<IconButton color="inherit" onClick={handleClick}>
<AccountCircle />
</IconButton>
<Menu
id="admin-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
component={RouterLink}
to="/profile"
onClick={handleClose}
>
Profile
</MenuItem>
<MenuItem
onClick={handleClose}
component={RouterLink}
to="/logout"
>
Logout
</MenuItem>
</Menu>
</Toolbar>
</AppBar>
</div>
);
};
export default Header;
Have you tried surrounding the IconButton with a ListItemSecondaryAction?
<ListItemSecondaryAction>
<IconButton onClick={handleOnClick}>
{openState ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</ListItemSecondaryAction>
I was trying to do something similar, where a list item had two clickable areas with two different actions: click the ListItem (to go to a page) or click the IconButton (to expand the ListItem) to display nested ListItems. Without this ListItemSecondaryAction, when I would click on a list item, it would both route and expand the ListItem, which was not desirable.
Adding the SecondaryAction separated click actions of the ListItem and the IconButton. The documentation isn't great, so it took me a while to understand the purpose, but it's here.

Antd horizontal sub menu "floating"

I have a very simple antd menu which I used following their docs. However, when the submenu opens it is floating (not attached to the main menu) and it really doesn't look good.
How do I fix this?
This is what my code currently looks like:
export function MainMenu () {
return (
<AntdLayout>
<Menu mode='horizontal' theme='dark' style={{ position: 'fixed', zIndex: 1, width: '100%', marginBottom: 100 }}>
<Menu.Item key='home'>
Home
</Menu.Item>
<SubMenu key='submenu' title='SubMenu'>
<Menu.Item key='1'>
Option 1
</Menu.Item>
<Menu.Item key='2'>
Option 2
</Menu.Item>
</SubMenu>
<Menu.Item key='contact'>
Contact
</Menu.Item>
</Menu>
</AntdLayout>
)
}
Here is a screenshot of what it looks like:
As its not adviced because Ant is a design system, you can achieve it by targeting the .ant-menu-submenu > .ant-menu selectors:
/* ./App.css */
.ant-menu-submenu > .ant-menu {
margin-top: -5px;
}
// index.js
import { Layout, Menu } from 'antd';
import 'antd/dist/antd.css';
import './App.css';
function MainMenu() {
return (
<Layout>
<Menu mode="horizontal" openKeys={['submenu']}>
<Menu.Item key="home">Home</Menu.Item>
<Menu.SubMenu
key="submenu"
title="SubMenu"
>
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
</Menu.SubMenu>
<Menu.Item key="contact">Contact</Menu.Item>
</Menu>
</Layout>
);
}

How to use Link components in Menu.List elements

I'm trying to get a semantic ui (react) menu list, which should be working with react router, which means I would like to use the Link component of react router
If I use this...
<Menu.Item name='profile'>
<Icon name='user' />
My profile
</Menu.Item>
...it gives me the result:
<a class="item">
<i aria-hidden="true" class="user icon"></i>
My profile
</a>
But I would like to get something like
<Link to='profile'>
<i aria-hidden="true" class="user icon"></i>
My profile
</Link>
This one doesn't work, as the syntax is wrong:
<Menu.Item name='profile' as={ <Link to='profile' /> }>
<Icon name='user' />
My profile
</Menu.Item>
You need use the SUIR's augmentation:
<Menu.Item as={ Link } name='profile' to='profile'>
<Icon name='user' />
My profile
</Menu.Item>
Use browserHistory.push instead ; It was provided also by react-router as an alternative of Link but non-markup :
import {browserHistory} from 'react-router';
redirect(to) {
browserHistory.push({
pathname: to
});
}
//......
<Menu.Item name="profile" onClick={this.redirect('/profile')}
<Icon name='user' />
My profile
</Menu.Item>
If you want to get /profile from name props , change the line by :
<Menu.Item name="profile" onClick={(event, itemProps) => this.redirect(itemProps.name)}
And if so , <Menu onItemClick={...} > is better than <Menu.item onClick={...} >

Categories

Resources