React-router: React Router parent “.active” class not active when child router loaded

Created on 9 Aug 2015  ·  15Comments  ·  Source: ReactTraining/react-router

This is how the routes are set up:

var RRoutes = (
<Route handler={App}>

    <Route name="home" path="/" handler={Page} />

    <Route name="portfolio" path="portfolio">
        <DefaultRoute handler={Page} />
        <Route name="portfolio.items" path=":page" handler={test} />
    </Route>

    <Route name="pages" path=":page" handler={Page} />


</Route>
);

When "/portfolio" page is loaded the link gets active. If the child route "portfolio.items" is loaded, the parent active link disappears.. Any suggestions how to get this to work? Is the problem because of the dynamic path?

Question asked here as well: http://stackoverflow.com/questions/31902524/react-router-parent-active-class-not-active-when-child-router-loaded

Most helpful comment

@taion, thank you for the quick reply and for the pointer to the example!

For anybody else coming across this: the problem in my case was that I defined a route on the form:

<Route path="main/:tab" component={...}/>

in which case Link active state does NOT work for nested routes. Instead, as per the examples, I had to rewrite this as:

<Route path="main">
    <Route path=":tab" component={...}/>
</Route>

which then works as expected.

All 15 comments

How does your link look like? Using a path (starting with a slash) for the to param will only set it active if the path matches exactly; using a name will set it active when the corresponding route is active (doesn't need to be the innermost matched route).

So I guess you're using <Link to="/portfolio" /> but you're looking for <Link to="portfolio" />

Oh wow, this fixed the problem. I spent hours trying many different things but never though of that.. Many thanks!

we need to document isActive way better.

I have the same problem, but in version 1+ where named routes have been removed. I noticed a discussion where this issue is raised:

https://github.com/rackt/react-router/issues/1514

The answer, by mjackson, is as follows:

_isActive will work the same way in 1.0 as it did in 0.13. The 1.0 implementation just isn't complete yet, but we're working on it._

However, in 1.0.3 (which I'm currently using), this still isn't working: for child routes, the link active state disappears. So, is the conclusion that this implementation still isn't complete? If so, is there a workaround?

Thanks!
Michael

@mdpedersen Check the active state example – by default <Link>s show as active on the matched route or any of its descendants.

@taion, thank you for the quick reply and for the pointer to the example!

For anybody else coming across this: the problem in my case was that I defined a route on the form:

<Route path="main/:tab" component={...}/>

in which case Link active state does NOT work for nested routes. Instead, as per the examples, I had to rewrite this as:

<Route path="main">
    <Route path=":tab" component={...}/>
</Route>

which then works as expected.

Man I wish there was something like reddit gold here on github, thanks a ton @mdpedersen. This helped me a thousand times.

And yes, I have to agree with @ryanflorence, there is practically no documentation about the active class, or at least its nowhere easy to be found. This little issue here is the best part of all.

Hi,

having the same issue here. I have the following routes:

<Provider store={store}>
    <Router history={browserHistory}>
      <Route path="/" name="login" component={Login}/>
      <Route path="/home" onEnter={requireAuth} component={App}>
        <IndexRoute name="home" component={Home}/>
      </Route>
    </Router>
  </Provider>

And the following links inside the App component

        <li className="nav-item">
          <Link className="nav-link" to="home">Home</Link>
        </li>
        <li className="nav-item">
          <Link className="nav-link" to="attributes">Attributes</Link>
        </li>
        <li className="nav-item">
          <Link className="nav-link" to="vision">Vision</Link>
        </li>

I would expect the Home link to be active but it is not. I looked through the documentation and cannot figure out what I'm doing wrong.

Amazing work with react-router, btw.

which version of react-router are you using @geclos?

1.0.3, soz I forgot to mention.

@geclos No problem :)
with v 1.0 they changed the activeClassName, you now have to pass it with every link. Documentation for this is here: https://github.com/rackt/react-router/blob/master/upgrade-guides/v1.0.0.md#active-class

So in your case you just have to do this:

        <li className="nav-item">
          <Link className="nav-link" to="/home" activeClassName="active">Home</Link>
        </li>
        <li className="nav-item">
          <Link className="nav-link" to="/attributes" activeClassName="active">Attributes</Link>
        </li>
        <li className="nav-item">
          <Link className="nav-link" to="/vision" activeClassName="active">Vision</Link>
        </li>

and the links will get the class active when they are.. well.. active :)

Notice how I also added a slash / in front of every link, this removes some weird browser reloading when clicking links!

Greetings to Barca, have some tapas for me.

You, my friend, rock. thanks.

I'll have some tapas for you :smile:

Trying to solve this, but no cigar, does anyone see what I'm doing wrong? (using version 2.8.1)

Routes:

    <Route path="/" component={App}>
        <IndexRoute component={MainPageContainer} />
        <Route path="venues">
            <IndexRoute component={VenuesPage} />
        </Route>
    </Route>

Links

<IndexLink to="/" activeClassName="active">Feed</IndexLink>
<Link to="/venues" activeClassName="active">Venues</Link>

<Link onlyActiveOnIndex activeClassName="active" to='/'>Home</Link>
@savovs use onlyActiveOnIndex will solve your problem

@taion @mdpedersen what about the scenario where you want to link to a route/subroute/:id? In my scenario we list products at /shop/products?foo=bar, and then the path to be pushed upon clicking a product is /shop/product/:productId.

We call a helper function to calculate it like so: this.props.router.push({ pathname: toProduct(ProductId), state: { modal: true } });

const getUrl = (value = 'main', props = {}) => {
  const route = routes.hasOwnProperty(value) ? routes[value] : value;
  return Object.keys(props).reduce((newRoute, key) => {
    if (newRoute.indexOf(key)) return newRoute.replace(key, props[key]);
    return newRoute;
  }, route);
};

export const toProduct = (productId) => {
  return getUrl(routes.product, { ':productId': productId });
};

But when I navigate to the product details page, isActive is no longer true, even though the URL includes /shop at the top level. Any ideas?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ryansobol picture ryansobol  ·  3Comments

alexyaseen picture alexyaseen  ·  3Comments

misterwilliam picture misterwilliam  ·  3Comments

ackvf picture ackvf  ·  3Comments

tomatau picture tomatau  ·  3Comments