Active NavLink to parent element

If you abandon the NavLink components altogether, you can create your own components that emulate the "activeness" of a NavLink by using useHistory() and useLocation() from react-router-dom.

Dashboard.js

const routeItems = [
  { route: '/route1', text: 'Route 1' },
  { route: '/route2', text: 'Route 2' },
];

<Router>
  <NavBar routeItems={routeItems} />
</Router>

In NavBar.js, we just need to check to see if the current active route is the same as the route for any individual item on the

NavBar.js

import { useHistory, useLocation } from 'react-router-dom';

const NavBar = (props) => {
  const { routeItems } = props;
  const history = useHistory();
  const location = useLocation();

  const navItems = routeItems.map((navItem) => {
    return (
      <div style={{
        backgroundColor: navItem.route === location.pathname ? '#ADD8E6' : '',
      }}
        onClick={() => {
          history.push(navItem.route);
        }}
      >
        {navItem.text}
      </div>
    );
  });

  return (navItems);
};
export default NavBar;

Can be achived with Route component

<ul>
  <Route path="/about">
    {({ match }) => <li className={match ? 'active' : undefined}><Link to="/about">About</Link></li>
  </Route>
</ul>

Reference: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Route.md#children-func


It doesn't seem like it is very easy to achieve. I used withRouter HOC described in react router docs. It gives access to { match, location, history } from props inside components located outside of Routess. In the example I wrapped Nav component to get location and its pathname. Here is the example code:

class Nav extends React.Component {
 getNavLinkClass = (path) => {
   return this.props.location.pathname === path ? 'active' : '';
 }
 render() {
  return (
    <nav>
      <ul>
        <li className={this.getNavLinkClass("/")}><NavLink exact to="/">Home</NavLink></li>
        <li className={this.getNavLinkClass("/about")}><NavLink to="/about">About</NavLink></li>
      </ul>
    </nav>
  )};
}
Nav = withRouter(Nav);

You will probably have to take care of params in your routes (if you have any), to match properly. But you still have to match for each path you have in your NavLink, which might not be pretty code. But the idea is that when the route is changed, Nav is rerendered and correct li is highlighted.

Here is a working example on codesandbox.