3

I'm using react-router v4. I find it confusing that when I click on <Link> component, the route is immediately changed. I want to stay at the current route before I fetch the data, not to switch the route and then fetch the data. I find that in react-router v3 there's a onEnter hook, but now in react-router v4, it is deprecated. So how can I fetch data right after I click on <Link> component and before the route is changed?

Example:

it's: at A -> click at <Link> to B -> fetching data for B -> render B

not: at A -> click at <Link> to B -> render Route B -> fetching data for B -> rerender B

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
ONI AKI
  • 33
  • 1
  • 7

1 Answers1

6

In react-router v4, you can make use of render prop to Route to replace the onEnter functionality existing in react-router v3

Suppose you have a route like in react-router v3

<Route path="/" component={Home} onEnter={getData} />

The Equivalent of this in react-router v4 would be

<Route exact path="/" render= {() => {getData(); return <Home data={this.state.data}/>}} />

However the suggested method is to make use of lifecycle methods in the component.

From the Github discussion:

We have no lifecycle hooks that receive props on initial render.

We no longer have a "route lifecycle". Instead, since <Match> components are real components (not pseudo-components like s were) they get to participate in React's lifecycle, which means they can just use componentWillMount.

So one of the suggested solution is:

v4 is all about routes just being components. That means taking advantage of lifecycle methods.

componentWillMount() { // or componentDidMount
  fetch(this.props.match.params.id)
}

componentWillReceiveProps(nextProps) { // or componentDidUpdate
  if (nextProps.match.params.id !== this.props.match.params.id) {
    fetch(nextProps.match.params.id)
  }
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 2
    I didn't mean to replace onEnter. For example, in your code, getData() may take 1 second or more. However, is returned before data gets back. So you are in { Home } and waiting for data. What I want to do is before you render , get the data, and then switch to { Home }. – ONI AKI Aug 01 '17 at 06:51
  • 1
    @ONIAKI, unfortunately v4 doesn't have a functionality like that. There are a few approached given in the Github discussion. It is encouraged to make use of lifecycle hooks for fetching data – Shubham Khatri Aug 01 '17 at 06:56
  • That's quiet confusing. I understand their philosophy but it blocks some ways to interact with users. Em... I've used vue.js and vue-router can do what exactly I say. Maybe I should consider switching to react-router v3 before I find a good solution. – ONI AKI Aug 01 '17 at 07:03
  • Indeed it does but we need to find ways around it – Shubham Khatri Aug 01 '17 at 07:05
  • I think I've found the correct way. Using history.push() can programmatically change the route, so I can fetch some data before route is changed. – ONI AKI Aug 06 '17 at 10:21
  • Adding side effects (getData()) to your render is a really poor pattern and should be avoided. React lifecycle methods are definitely the way to go – Ulysse Mizrahi Dec 12 '18 at 15:42
  • @UlysseMizrahi I did mention the same in my answer. – Shubham Khatri Dec 12 '18 at 16:00
  • yes but the way the answer is formulated makes it sound like the render method is the default way to do it, and the lifecycle method is just a "better" way to do it, when the lifecycle method is really the only decent answer. I would not mention the first solution at all, people may brush over your further lifecycle explanation and use that one. – Ulysse Mizrahi Dec 13 '18 at 16:12