Mas Bagol
Mas Bagol

Reputation: 4617

Correct way to fetch data when switching route on same level in react-router?

What is the correct way to fetch data when switching route on same level? Because, according to this, switching route on same level will only call componentWillReceiveProps and componentDidUpdate. And componentDidMount is only called the first time route is entered.

With route configuration like this:

render((
  <Provider store={store}>
    <Router>
      <Route path="/" component={App}>
        <Route path="/:userId" component={Profile}/>
      </Route>
    </Router>
  </Provider>
), document.getElementById('root'));

The Profile component is:

class Profile extends React.Component {
  componentDidMount() {
    // initial data
    this.fetchUserData();
  }
  componentWillReceiveProps(nextProps) {
    if (this.props.params.userId !== nextProps.params.userId) {
      this.fetchUserData();
    }
  }
  shouldComponentUpdate(nextProps) {
    return this.props.params.userId !== nextProps.params.userId;
  }
  render() {
    return (
      <div className="profile"></div>
    );
  }
}

The data will be stored in application state field (props.userData). But, that's obviously will mess up with rendering cycle because route is switched before fetch data is finished.

But, if I change to this:

// deepEqual is function to check object equality recursively
componentWillReceiveProps(nextProps) {
  if (!deepEqual(this.props.userData, nextProps.userData)) {
    this.fetchUserData();
  }
}
shouldComponentUpdate(nextProps) {
  return !deepEqual(this.props.userData, nextProps.userData);
}

This won't work because before userData is fetched, those props is deeply equal.

So, how to fetch data when switching route on same route level?

Upvotes: 2

Views: 2119

Answers (1)

Jeremy Gordon
Jeremy Gordon

Reputation: 551

From the React Router docs:

componentDidMount () {
  // fetch data initially in scenario 2 from above
  this.fetchInvoice()
},

componentDidUpdate (prevProps) {
  // respond to parameter change in scenario 3
  let oldId = prevProps.params.invoiceId
  let newId = this.props.params.invoiceId
  if (newId !== oldId)
    this.fetchInvoice()
}, 

When route changes this.props.params.userId will update, which is caught in componentDidUpdate, and fires off a fetch. Of course this fetch will likely update state or props firing another re-render to show the fetched data.

Upvotes: 3

Related Questions