I'm currently creating a multilevel sidebar menu in REACT and I want to dynamically add active class to parent <li> when the current route is active.
The code below is how I do it for a single menu.
<Route
  path={this.props.to}
  exact={this.props.activeOnlyWhenExact}
  children={({ match }) => (
    <li className={match ? "active" : ""}>
      <Link to={this.props.to} activeClassName="active">
        <span className="sidebar-mini-icon">
          <i className={this.props.icon}></i></span>
          {this.props.label}
      </Link>
    </li>
  )}
/>
Now I wonder how I do it with multilevel menu. My menu looks like this;

As you can see, only the menu has the active class. Here's my code for the multi level menu:
<Route
  path={this.props.to}
  exact={this.props.activeOnlyWhenExact}
  children={({ match }) => (
  <li>
    <a data-toggle="collapse" href="#Collapse">
      <span className="sidebar-mini-icon">
        <i className={this.props.icon}></i>
      </span>
      <span className="sidebar-normal">
        {this.props.name}
        <b className="caret"></b>
      </span>
    </a>
    <div class="collapse" id="Collapse">
       <ul className="nav">
         {this.props.children}
       </ul>
    </div>
  </li>
  )}
/>
I'm using React Router. Any help will be appreciated. Thank you.
The solution would depend on your route configuration. If you are using non-exact routes, the solution with NavLink would be the most applicable.
Example:
routes.jsx
<Route path="/parent/child-a">
  <ChildA />
</Route>
<Route path="/parent/child-b">
  <ChildB />
</Route>
<Route path="/parent">
  <Parent />
</Route>
Using the above structure, /parent/child-a would match two routes (/parent and /parent/child-a) and the activeClassName prop on the NavLink would be applied on both HTML element.
The "challenge" with the above structure is that you are going to render <Parent /> in all three cases.
This could be solved by using nested/child routes.
routes.jsx
<Route path="/parent">
  <NestedRoutes />
</Route>
nestedRoutes.jsx
<Route path="/parent/child-a" exact>
  <ChildA />
</Route>
<Route path="/parent/child-b" exact>
  <ChildB />
</Route>
With the updated structure above, /parent/child-a would match the top-level route (and as a result add the activeClassName to your HTML element) and also match the child route and add the activeClassName there too.
Note that if you need /parent to also work as a route, you need to update your nested routes as follows:
nestedRoutes.jsx
<Route path="/parent" exact>
  <Parent />
</Route>
From my experience, if you find yourself handling these cases manually through JavaScript or useLocation you might want to revisit your route configuration. react-router is an excellent library in its simplicity and will probably handle your case out of the box.
You can use React router's nav link
<NavLink to="/faq" activeClassName="selected">
  FAQs
</NavLink>
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With