16
votes

I am trying to style my navigation by using the react activeClassName attribute. So far it works as expected, but there is a problem - my first nav links points to the root route(/). So even when on another URL it will register that URL (for example /skills) and root as active (so 2 menu items get styled).

Is there an easy workaround for this? Should I just define the Root route as something else (for example /home)?

My header:

import React, { PropTypes } from 'react';
import { Link, IndexLink } from 'react-router';

const Header = () => {
    return (
        <div className="header">
            <div className="headerImage"></div>
            <ul className="headerNav">
                <li className="headerNavLink"><Link to="/" activeClassName="activeLink">introduction</Link></li>
                <li className="headerNavLink"><Link to="/skills" activeClassName="activeLink">skills</Link></li>
                <li className="headerNavLink"><Link to="/portfolio" activeClassName="activeLink">portfolio</Link></li>
            </ul>
        </div>
    );
};

export default Header;

routes.js:

import React from 'react';
import { Route, IndexRoute } from 'react-router';
//Import app
import App from './components/App';
//Import pages
import IntroductionPage from './components/introduction/IntroductionPage';
import SkillsPage from './components/skills/SkillsPage';
import PortfolioPage from './components/portfolio/PortfolioPage';

//Define routes
export default (
    <Route path="/" component={App}>
        <IndexRoute component={IntroductionPage} />
        <Route path="skills" component={SkillsPage} />
        <Route path="portfolio" component={PortfolioPage} />
    </Route>
);

So to clarify, I would like my home route to not be active when on another route.

What am I doing wrong?

Thanks

4

4 Answers

24
votes

I'd like to reference the docs for React Router (react-router-dom, currently v5) and the sources. This is the up-to-date way to implement this:

exact: bool

When true, the active class/style will only be applied if the location is matched exactly.

<NavLink exact to="/profile">
  Profile
</NavLink>

Here is a real world working example:

<ul class="nav flex-column">
    <li class="nav-item">
      <NavLink className="nav-link" activeClassName="active" to="/" exact>Home</NavLink>
    </li>
    <li class="nav-item">
      <NavLink className="nav-link" activeClassName="active" to="/calendar">Calendar</NavLink>
    </li>
    <li class="nav-item">
      <NavLink className="nav-link" activeClassName="active" to="/page">Page</NavLink>
    </li>
</ul>
13
votes

Just like also to share this if you use "react-router-dom": "4.1.1",

export const routes = <Index>
    <Route exact path='/' component={Home} />
    <Route path='/about' component={About} />
</Index>;

Then your navigation menu is

<NavLink exact={true} activeClassName='active' to="/">
   Home
</NavLink>
<NavLink activeClassName='active' to="/bout">
    About
</NavLink>

Just specify also the "exact={true}" props for the NavLink and it should work as expected.

Thanks, Hope this helps.

11
votes

You can use <IndexLink> or set onlyActiveOnIndex prop for links that are not to be highlighted when their children paths are active:

<li className="headerNavLink"><IndexLink to="/" activeClassName="activeLink">introduction</IndexLink></li>

or

<li className="headerNavLink"><Link to="/" activeClassName="activeLink" onlyActiveOnIndex>introduction</Link></li>
1
votes

In react-router-dom ^4.0 there's no IndexRoute or IndexLink. Instead you need to specify the route path as exact and the child routes should be specified inside the <Route>'s component. See this answer for more details: https://stackoverflow.com/a/43311025/2713729