Using React Router and Material UI, I'm trying to set the navigation item selected state based on the current URL path. If a user comes to a specific page, it should set the selected state of the appropriate link in the sidebar.
This is the current setup, but not sure what property I'm missing to set the active state based on the URL path using React Router
data.navigation
"navigation":[
{
"label":"Introduction",
"path": "/"
},
{
"label":"Page Two",
"path": "pagetwo"
}
]
import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom';
const [selectedIndex, setSelectedIndex] = useState(0);
const handleListItemClick = (event, index) => {
setSelectedIndex(index);
};
{data && data.navigation.map((item, i) =>
<Link key={i} to={`${item.path}`} className={classes.link}>
<ListItem button selected={selectedIndex === i} onClick={(event) => handleListItemClick(event, i)}>
<ListItemText className={classes.navLink}>{item.label}</ListItemText>
</ListItem>
</Link>
)}
CodePudding user response:
Here is a sample that I have set up to get this working. I had to keep exact
to get it working.
https://stackblitz.com/edit/react-wvhugc?file=src/App.js
import React from 'react';
import './style.css';
import {
BrowserRouter as Router,
Switch,
Route,
NavLink,
} from 'react-router-dom';
import ListItemText from '@mui/material/ListItemText';
import ListItem from '@mui/material/ListItem';
export default function App() {
const navigation = [
{
label: 'Introduction',
path: '/',
},
{
label: 'Page Two',
path: '/pagetwo',
},
];
return (
<Router>
{navigation.map((item, i) => (
<NavLink
exact
activeStyle={{
fontWeight: 'bold',
color: 'red',
}}
key={i}
to={`${item.path}`}
>
<ListItem button>
<ListItemText>{item.label}</ListItemText>
</ListItem>
</NavLink>
))}
<Switch>
<Route exact path="/">
<div>Home</div>
</Route>
<Route path="/">
<div>Page 2</div>
</Route>
</Switch>
</Router>
);
}
CodePudding user response:
If you make each link a component, you can use useRouteMatch
like in the "custom link" example in the React Router docs.
function NavigationLink(props) {
const match = useRouteMatch({
to: props.path,
});
// update the link class to set styles appropriately depending
// on whether active is true or false
const classes = useStyles({ active: match != null });
return (
<Link to={props.path} className={classes.link}>
<ListItem button selected={props.selected} onClick={props.onClick}>
<ListItemText className={classes.navLink}>{props.children}</ListItemText>
</ListItem>
</Link>
);
}
// In your existing component
data.navigation.map((item, i) => (
<NavigationLink
key={i}
path={item.path}
selected={selectedIndex === i}
onClick={(event) => handleListItemClick(event, i)}
>
{item.label}
</NavigationLink>
));