Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router v4 NavLink active route

I'm trying to port my project from using v3 of react-router to v4 of what is now called react-router-dom. Now the problems arise when I have a MenuBar component, which is completely separate from the routing logic (as you'd expect), because it will show the exact same links whatever the current path may be. Now that worked all nicely with v3, but now when I'm using NavLink, which has the same activeClassName property, the active route does not update on the NavBar, only on refresh. That seems a bit dumb, so there must be a way around this.

export default @inject('ui') @observer class App extends Component {
  render() {
    return (
      <Router>
        <div className={ styles.wrapper }>
          <Sidebar />
          <main className={ `${styles.main} ${!this.props.ui.menuOpen && styles.closed}` }>
            <Route exact path="/" component={ HomePage } />
            <Route path="/signup" component={ SignUpPage } />
            <Route path="/login" component={ LoginPage } />
            <Route path="/about" component={ AboutPage } />
          </main>
          <footer className="site-footer"></footer>
        </div>
      </Router>
    );
  }
}

The above is my main App logic and as you can see the routes are nested, but the Router itself wraps around the whole component.

What should I add to make them work again? (They do work properly on page refresh)

like image 610
Dániel Emőd Kovács Avatar asked Mar 12 '17 20:03

Dániel Emőd Kovács


People also ask

How do I make my NavLink active?

NavLink instead of Link The first method is to use the react-router-dom inbuilt method of NavLink instead of Link. The NavLink supports activeClassName which can help us assign active className to the link. Paste the below-updated code in your project Header. js file.

Should I use HashRouter or BrowserRouter?

HashRouter: When we have small client side applications which doesn't need backend we can use HashRouter because when we use hashes in the URL/location bar browser doesn't make a server request. BrowserRouter: When we have big production-ready applications which serve backend, it is recommended to use <BrowserRouter> .


1 Answers

Based on your usage of the @observer decorator, it appears that you are using mobx-react. The thing to understand about observer is that it implements shouldComponentUpdate to optimize rendering performance. That sCU call will look at the current and next props, and if there is no difference, it will not re-render. This is a problem because by default, React Router uses the context to pass data and relies on elements re-rendering to get the updated values, but observer's sCU has no way to detect context changes.

The way that you can get around this is by passing the location object as a prop to the component that is wrapped by observer. Then, when the location changes, observer's shouldComponentUpdate will detect the difference and re-render.

You can see the blocked updates guide for more information.

like image 183
Paul S Avatar answered Sep 28 '22 22:09

Paul S