96

I've created a bootstrap-style sidebar using Link. Here is a snippet of my code:

<ul className="sidebar-menu">
  <li className="header">MAIN NAVIGATION</li>
  <li><Link to="dashboard"><i className="fa fa-dashboard"></i> <span>Dashboard</span></Link></li>
  <li><Link to="email_lists"><i className="fa fa-envelope-o"></i> <span>Email Lists</span></Link></li>
  <li><Link to="billing"><i className="fa fa-credit-card"></i> <span>Buy Verifications</span></Link></li>
</ul>

I want to set the class for the active path to active on the wrapping element <li>. I see there are other solutions out there that show how to do this like Conditionally set active class on menu using react router current route, however I don't think that it's the best way to set an active class on a wrapper to a Link.

I also found https://github.com/insin/react-router-active-component but it feels like it is unnecessary.

In React Router, is this possible or do I need to use an external solution?

Pavindu
  • 2,684
  • 6
  • 44
  • 77
coderberry
  • 3,040
  • 3
  • 26
  • 28

29 Answers29

108

On the Link component you can now add activeClassName or set activeStyle.

These allow you to easily add styles to the currently active link.


Previously, you could create a custom component that works like a wrapper to Link with the following logic.

In a file called nav_link.js

import React from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';

class NavLink extends React.Component {
    render() {
        var isActive = this.context.router.route.location.pathname === this.props.to;
        var className = isActive ? 'active' : '';

        return(
            <Link className={className} {...this.props}>
                {this.props.children}
            </Link>
        );
    }
}

NavLink.contextTypes = {
    router: PropTypes.object
};

export default NavLink;

And use it as given below in your component:

// ...
import NavLink from "./nav_link";
// ...

<nav>
    <ul className="nav nav-pills pull-right">
        <NavLink to="/">
            <i className="glyphicon glyphicon-home"></i> <span>Home</span>
        </NavLink>
        <NavLink to="about">
            <i className="glyphicon glyphicon-camera"></i> <span>About</span>
        </NavLink>
    </ul>
</nav>
GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
Vijey
  • 6,536
  • 7
  • 43
  • 50
  • contentTypes in NavLink component should be static property not an instance property. Please correct. – Oleh Nov 17 '16 at 14:33
  • 2
    Why not use `activeStyle` or `activeClassName` exposed by `react-router`. There is some [documentation](https://github.com/reactjs/react-router-tutorial/tree/master/lessons/05-active-links) around it. – Hozefa Nov 21 '16 at 23:32
  • 1
    It appears that this no longer works as of react-router v4.0.0, as `router.isActive` no longer exists. See: https://github.com/react-bootstrap/react-router-bootstrap/issues/186 – chazzlabs Mar 14 '17 at 02:02
  • 1
    With react-router 3.0.0 , got `TypeError: Cannot read property 'location' of undefined` – Mithril Aug 17 '17 at 01:45
  • Yes it should be the accepted answer. It worked beautifully for me! However, there is more to the config than just these steps. For me, it just made sure that my components in my nav were wrapped with this. There were other steps that made this work in the grand scheme of things. I will share them here a bit later when I have a moment. – Maria Campbell Oct 04 '17 at 11:35
  • When I tested this with Jest, it failed. It returned an error and/or undefined. So I looked into things further and played around more with code. I finally came up with a solution and it passed! I will be writing a post about it over the weekend and will share my results here. it was tricky and I had to do a good deal of research, refactoring and testing before I got there! So I'm sorry that I had to subsequently downvote this. Technically it worked, but it failed my test. – Maria Campbell Oct 05 '17 at 23:06
  • I used this code but when I navigate on my menu links, the class is not changing until I reload the page. What should I do to make it rerendered again every time I click on a Link? – cusmar Jun 04 '18 at 10:07
86

React-Router V4 comes with a NavLink component out of the box

To use, simply set the activeClassName attribute to the class you have appropriately styled, or directly set activeStyle to the styles you want. See the docs for more details.

<NavLink
  to="/hello"
  activeClassName="active"
>Hello</NavLink>
Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82
Matt
  • 4,462
  • 5
  • 25
  • 35
19

For me what worked has is using NavLink as it has this active class property.

  1. First import it

    import { NavLink } from 'react-router-dom';
    
  2. Use an activeClassName to get the active class property.

    <NavLink to="/" activeClassName="active">
     Home
    </NavLink>
    
    <NavLink to="/store" activeClassName="active">
     Store
    </NavLink>
    
    <NavLink to="/about" activeClassName="active">
     About Us
    </NavLink>
    
  3. Style your class in the css by the property active.

    .active{
      color:#fcfcfc;
     }
    
Fahad Shinwari
  • 968
  • 7
  • 7
  • 3
    this works, thanks, found a solution to turn off the Home always being active also: https://stackoverflow.com/questions/51214763/navlink-from-react-router-dom-home-always-active/51214772 – Hank May 17 '21 at 17:13
14

This is my way, using location from props. I don't know but history.isActive got undefined for me

export default class Navbar extends React.Component {
render(){
const { location } = this.props;

const homeClass = location.pathname === "/" ? "active" : "";
const aboutClass = location.pathname.match(/^\/about/) ? "active" : "";
const contactClass = location.pathname.match(/^\/contact/) ? "active" : "";


return (
<div>
      <ul className="nav navbar-nav navbar-right">
        <li className={homeClass}><Link to="/">Home</Link></li>
        <li className={aboutClass}><Link to="about" activeClassName="active">About</Link></li>
        <li className={contactClass}><Link to="contact" activeClassName="active">Contact</Link></li>
      </ul>

</div>
    );}}
resurrecteds
  • 5,176
  • 2
  • 16
  • 18
gema
  • 523
  • 1
  • 7
  • 17