25

I need a help with react-router v2+ I have to change class of navbar when route changed for example for route /profile className will be "profile-header" I tried to use this.props.location in navbar component but it shows undefined

Hope your help

Андрей Гузюк
  • 2,134
  • 6
  • 29
  • 53

5 Answers5

43

Your navbar component (as you described it in your question) is probably not the route component, right? By route component I mean the one that you use in your react-router configuration that is loaded for a specific route.

this.props.location is accessible only on such route component, so you need to pass it down to your navbar.

Let's take an example:

Your router config:

<Router>
    <Route path="/" component={App}>
    // ...
</Router

Route component App:

class App extends React.Component{
  // ...
  render() {
    return <Navbar location={this.props.location}/>
  }
}
szymonm
  • 1,053
  • 8
  • 12
9

There could be a scenario where you may not have access to props.location to pass to the nav component.

Take for example - We had a header component in our project which was included in the routing switch to make it available to all routes.

<Switch>
  <Fragment>
    <Header/>
    <Route path='..' component={...}/>
    <Route path='..' component={...}/>
  </Fragment>
</Switch>

In the above scenario there is no way to pass the location data to the Header component.

A better solution would be to us the withRouter HOC when a component is not being rendered by your router. You will still have access to the router properties history, match and location when you wrap it in the withRouter HOC:

import { withRouter } from 'react-router-dom'
.... 
....
export default withRouter(ThisComponent)
varoons
  • 3,807
  • 1
  • 16
  • 20
2

react-router v4

From documentation:

  1. <Route> component property should be used, when you have an existing component. <Route> render property takes an inline function, that returns html.

  2. A <Route> with no path will always match.

Based on this, we can make a <Route> wrapper to any level of your html structure. It will always be displayed and have access to the location object.

As per your request, if a user comes to /profile page, the <header> will have profile-header class name.

<Router>
    <Route render={({ location }) =>
        <header className={location.pathname.replace(/\//g, '') + '-header'}>
            // header content...
        </header>

        <div id="content"></div>

        <footer></footer>
    } />
</Router>
Community
  • 1
  • 1
Arsen K.
  • 5,494
  • 7
  • 38
  • 51
1

I couldn't solve it with the solutions given here and here is what worked for me:

I imported history into my component and assigned history.location.pathname to a variable which I later used for dynamic style manipulation.

0

In case you are rendering the component with pre-defined location.state values, first set your state with props.location.state then use your state data in your elements.

ETZE
  • 145
  • 5
  • I tried it in `render()` method. I tried to set state from `props.location`. But it gave infinite loop of rendering as `setState() -> render() -> serState() -> render() ...` likewise. So better to use approach mentioned at https://stackoverflow.com/a/59264602/1994950 answer – Kushal Dec 10 '19 at 10:13