Home > front end >  Set active link in React Router based on current path
Set active link in React Router based on current path

Time:09-22

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

  • Related