Get active route inside React component using React Router


#1

Hi guys, I have a route which looks like this (unrelevant code omitted for brevity):

<Route path="/:postId/:slug" component={ SingleArticle }></Route>

In one of my components, I need to know if that’s the currently active route. In the React Router docs, apparently the only function I could use to do that is isActive which, according to their docs, works like this:

Returns true or false depending on if the pathOrLoc is active. Will be true for every route in the route branch matched (child route is active, therefore parent is too), unless indexOnly is specified, in which case it will only match the exact path.

A route is only considered active if all the URL parameters match, including optional parameters and their presence or absence.

However, only explicitly specified query parameters will be checked. That means that isActive({ pathname: ‘/foo’, query: { a: ‘b’ } }) will return true when the location is /foo?a=b&c=d. To require that a query parameter be absent, specify its value as an explicit undefined, e.g. isActive({ pathname: ‘/foo’, query: { a: ‘b’, c: undefined } }), which would be false in this example.

I’ve tried using this.context.router.isActive({ pathname: '/:postId/:slug' }) and this.context.isActive({ pathname: '/${/\d+/}/${/[A-Za-z0-9_\-]+/}' }) but none worked. How could I let my react component know if this route is currently active?


#2

Here’s an almost identical question to yours:

It looks like the problem is that:

isActive takes a location descriptor, not a route path

So instead of: this.context.router.isActive({ pathname: '/:postId/:slug' })
You want to do: this.context.router.isActive({ pathname: '/5345435354/345535' })

I can only see this functionality being useful in an extremely specific and limited set of cases however (like if you had a menu item component that you wanted to behave [and not just look] differently when its associated route was active). There are already included Link functions to decorate links when their associated route is active. And it’s easy to tell if a given component is currently being rendered with react lifecycle hooks. I wonder if there is a better, simpler way to get the functionality you are after. Can you explain your problem in more detail?


#3

check out meteor chef’s base github in the modules folder


#4

Sorry for the duplicate question, I couldn’t find similar questions when I was writing mine, maybe because of the wording of the question.

So, I have a Single Article page, which is a React component and is associated to the route I mentioned in the question. And I also have a fixed Navigation Bar, which is also a React component, and needs to add a class (nav-shrink) to change it’s height based on the current active page. Basically, I need the Navigation Bar to know what’s the active route, and add or remove a css class based on that information. Ideally I’d just get the name active route or something similar, but React Route apparently does not provide this kind of functionality


#5

React Router does offer that functionality if you want to update the className of an anchor tag <a> based on whether it is pointing to the active route. Check out this tutorial:


#6

I know that it is possible to change a Link’s styling based on the active route, however I’m trying to change the styling of a div component, I don’t see how I could do that unless I wrap my entire component inside a Link, which I don’t think would make much sense. The temporary solution I’ve found is to use an onEnter hook on the Single Article page route that adds the ‘nav-shrink’ class to the Navigation Bar and an onLeave hook to remove it, which I don’t know if it’s appropriate, in a ideal scenario the Navigation Bar component manages it’s own classes and no external code should change it.


#7

It sounds like you could use isActive as we discussed before. Generally if you have to change some master layout property based on whats being rendered, I’d suggest refactoring to where it happens implicitly as part of the flow of the app, and not explicitly with route matching. Without knowing the details, I’d guess that you can create a few different navbars for the different scenarios (sharing code using the concept of higher order components), and use them as the component to be rendered at different routes:

<Router history={hashHistory}>
    <Route path="/" component={App}>
      <IndexRoute component={Home}/>

      <Route path="/repos" component={ReposNavbar}>
        <Route path="/repos/:userName/:repoName" component={Repo}/>
      </Route>
      <Route path="/posts" component={PostsNavbar}/>
        <Route path="/posts/:postId/:slug" component={Post}/>
    </Route>
  </Router>

#8

Indeed, this solutions takes a more component-oriented and modular approach. Thanks!