Reputation: 2837
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"
},
Upvotes: 1
Views: 2466
Reputation: 12691
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
}
}
Upvotes: 1
Reputation: 9
import Switch from react-router-dom to your App.js
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
const App = () => (
<Provider store={store}>
<Router>
<div>
<Navbar />
<div className="container">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/account" component={Account} />
</Switch>
</div>
</div>
</Router>
</Provider>
);
export default App;
don't forget to import Navbar, Home, and Account
Upvotes: 0