Ad

Navbar Component Location Doesn't Update When Route Changed, With React Router

- 1 answer

I'm building an app in React and am trying to get the navbar to update when the user navigates to a different page. However it's inconsistent about detecting the change of location prop.

If I go to the Home page and refresh the page, then click the Account link, the Account and Navbar location.pathname prop both change from "/" to "Account", as expected, and the console correctly writes "change".

If I then click the Home link, the Navbar again correctly detects the route change.

However, if I now click "Account" again, the Navbar's location does not update, it remains "/" and the change isn't detected.

I can't see what's different between these two cases, but it consistently works the first time I click "Account" and not the second.

I've read the React Router docs about blocking components, and I don't think that's the problem because the navbar is a top level component, I'm using 'location' as a prop, I'm not using purecomponent, and the Account component does update. And I think if this was the problem, it would never work?

Can anybody suggest how I can get the navbar to consistently detect when the route changes? Thank you!

Navbar.js:

class Navbar extends Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate = (prevProps) => {
        console.log('***');
        console.log('nav old pathname', prevProps.location.pathname);
        console.log('nav new pathname', this.props.location.pathname);

        if (prevProps.location.pathname !== this.props.location.pathname) {
            // this usually doesn't trigger on navigate
            console.log('change');
        }
    }

    render() {
        ...render my html
    }
}

export default connect(mapStateToProps)(withRouter(Navbar));

App.js:

const App = () => (
    <Provider store={store}>
        <Router>
            <div>
                <Navbar />
                <div className="container">
                    <Route exact path="/" component={Home} />
                    <Route exact path="/account" component={Account} />
                </div>
            </div>
        </Router>
    </Provider>
);

export default App;

From package.json:

"dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.18",
    "@fortawesome/free-regular-svg-icons": "^5.8.2",
    "@fortawesome/free-solid-svg-icons": "^5.8.2",
    "@fortawesome/react-fontawesome": "^0.1.4",
    "bootstrap": "^4.2.1",
    "classnames": "^2.2.6",
    "formik": "^1.5.7",
    "i": "^0.3.6",
    "jquery": "^3.4.0",
    "jwt-decode": "^2.2.0",
    "normalizr": "^3.3.0",
    "npm": "^6.9.0",
    "prop-types": "^15.7.2",
    "react": "^16.8.2",
    "react-dom": "^16.8.2",
    "react-markdown": "^4.0.6",
    "react-redux": "^6.0.0",
    "react-router-dom": "^4.3.1",
    "react-scripts": "3.0.0",
    "react-widgets": "^4.4.11",
    "reactstrap": "^7.1.0",
    "redux": "^4.0.1",
    "redux-devtools-extension": "^2.13.8",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "updeep": "^1.1.0"
  },
Ad

Answer

The problem is in this line :

export default connect(mapStateToProps)(withRouter(Navbar));

You are not using PureComponent, but redux connect is. You can fix this by :

1.Invert the composition :

export default withRouter(connect(mapStateToProps)(Navbar));

2.Pass the location props down in mapStateToProps:

const mapStateToProps(state, ownProps) {
   return {
      location: ownProps.location
   }
}
Ad
source: stackoverflow.com
Ad