2

This problem is driving me insane, I got a simple little app created by create-react-app and I am using React-Router.

JSX:

<Router>
    <Route path="/pages/:pageId" component={Page} />
</Router>

In the Page component I have an fetch on componentDidMount, its working as expected first time the route is loaded.

For example I visit: /pages/13 and then it fetches that pages data, but when I am on: /pages/13 and then click on a Link component (imported from React-Router) redirecting me to: /pages/15 - the pageId prop is then updated but it never re-renders.

The Page component never run componentWillUnmount before, or componentDidMount after.

Expected behavior:

  1. Visit: /pages/13render()componentDidMount()render()
  2. Click on Link component /pages/15componentWillUnmount()render()componentDidMount()render()

I am using the following versions:

  • react: 16.3.2
  • react-dom: 16.3.2
  • react-router-dom: 4.2.2

What am I doing wrong? I am still pretty new to React so be nice :)

Community
  • 1
  • 1
MrZiggyStardust
  • 693
  • 5
  • 19
  • 2
    Possible Duplicate of [React doesn't reload component data on route param change](https://stackoverflow.com/questions/48139281/react-doesnt-reload-component-data-on-route-param-change/48139367#48139367) – Shubham Khatri Apr 27 '18 at 13:17

2 Answers2

2

Your problem is that componentDidMount only executes when the component is completely mounted, and this only occurs one time. In this case, changing the route param doesn't change the component, I mean, you still being in the same component when you change the pageId, thus the componentDidMount is never executed again. What could you do then?, well, I suggest you to look into componentWillReceiveProps(newProps) method, this is executed whenever the component's props are about to be modified, which in this case, is what you are looking for, because, according to this:

You’ll have access match objects in various places: Route component as this.props.match; Route render as ({ match }) => (); Route children as ({ match }) => (); withRouter as this.props.match; matchPath as the return value;

the match object (which contains the route params) is given through component's props.

So, short answer. Use componentDidMount for first time fetching, and then use componentWillRecieveProps(newProps) for all the rest fetching calls.

check this for more info.

Note: I didn't know that componentWillRecieveProps(newProps) was about to be somewhat deprecated, anyways, it suggest you to use getDerivedStateFromProps(nextProps, prevState) which is basically the same

Gustavo Topete
  • 876
  • 6
  • 14
0

When parameter is changing, your Route doesn't remount your component. This is an expected behaviour. You should catch the parameter changing via componentWillReceiveProps, otherwise if you wish to force remounting, you should use <Route path="/your/path/with/:id" render={props => <Component {...props} key={props.params.id} />

Limbo
  • 1,529
  • 11
  • 32