React-router: Data fetching in 1.0.0’s onEnter — possible? Good idea in the first place?

Created on 23 Jun 2015  Â·  16Comments  Â·  Source: ReactTraining/react-router

I'm wondering what the recommended practice for fetching data necessary for rendering a route is in 1.0.0. Let’s say a user browses to /post/123, I'd like to make a call to my API to make sure that this Post is in my stores and ready to go.

At the moment I've been firing these API actions in componentWillMount, but part of me wonders if it would be better to do this kind of work in 1.0.0 Route’s onEnter? I can't get that to work as my API actions return Promises and I can’t see anyway to trigger a transition manually, but then again, how would I display any visual indication that the app is loading something this way?

To sum it up, can onEnter be used to defer a transition until a promise is fulfilled, and is this a good idea in the first place? Thanks very much.

Most helpful comment

@mjackson IMHO having top-level components load their own data is both more complex from a programming perspective (because at least two states are needed: loading/loaded) and transitioning before data is loaded is janky as components all resize to accommodate data as it arrives. I'd much rather have route transitions take a little longer. The perception of slowness can be solved with visual feedback such as loading indicators.

If it is indeed possible to do async data loading with onEnter then I suggest that you retain the name and not rename it :) Might I also suggest that this becomes an officially supported use case - instead of advocating not data loading in onEnter how about just explaining the trade-offs? Not everybody shares the opinion that data loading must not be async.

All 16 comments

I think it is a valid example how onEnter should be used. Please check the code of the transition hooks. There you get a callback. You have to maintain the transition object with your navigation decission and call that callback to inform the router, that your async task is over (e.g. when your promise is resolved).

https://github.com/rackt/react-router/blob/master/modules/RoutingUtils.js#L187

No, do not fetch data in onEnter. This is always a bad idea because the UI will not be responsive while you're fetching data.

Please see the AsyncProps code (still experimental) for some ideas we have around how to do this properly.

Great, I was hoping for a clarification like this. Thank you for being so attentive to this repo’s issues!

Any update on async-loading in 1.0? I have noticed that the AsyncProps and async-data example have been removed from master...

@mjackson can you clarify what you mean by "UI will not be responsive while you're fetching data"? I come from an Angular.js background used the ui-router which followed the paradigm of data being loaded asynchronously in the routes. When the 'resolve' promises either all resolved or one rejected, there would be a route transition.

I'm trying to accomplish this with react-router but it feels like I'm fighting it. Programmatically, having the data injected into the top-level components in the router is desirable to me. What is it about the designed of react-router that makes this undesirable? Is it a deliberate choice?

@freshtonic onEnter is your chance to redirect, not fetch data. We should probably just call the method doYouWantToRedirect because everyone tries to use it to fetch data :P

If you don't mind waiting for your data to load before you transition, you _can_ use onEnter to fetch data. But your page will feel sluggish because the router doesn't attempt to update state until all onEnter hooks are finished (so it knows if it needs to redirect or not).

@mjackson IMHO having top-level components load their own data is both more complex from a programming perspective (because at least two states are needed: loading/loaded) and transitioning before data is loaded is janky as components all resize to accommodate data as it arrives. I'd much rather have route transitions take a little longer. The perception of slowness can be solved with visual feedback such as loading indicators.

If it is indeed possible to do async data loading with onEnter then I suggest that you retain the name and not rename it :) Might I also suggest that this becomes an officially supported use case - instead of advocating not data loading in onEnter how about just explaining the trade-offs? Not everybody shares the opinion that data loading must not be async.

@mjackson FWIW, I'd be more than happy to document the trade-offs and submit a PR if this becomes an officially supported use case.

Is there any best practice solution for fetching data both server side and client side in 1.0 ?

Is there any update on it in 2.0 release? Is it still considered bad practice to use onEnter to fetch data required to display the page? In both Angular 1.x (using route's resolve property) and in Ember (using route's model property) there's a built-in way of fetching data asynchronously _before_ rendering the template. If one is not supposed to use onEnter for it, then what's the alternative? If fetching data is async then it shouldn't really cause UI to be unresponsive, right?

@szimek You might want to look at async-props, as it handles both data loading at component entrance and all the server rendering nonsense too.

@timdorr Thanks!

@timdorr But why is this solution better than onEnter ? Pausing transition before necessary data loaded makes sense because sometimes after this you no need to render the component. Suppose api responses with 404 so it is very likely you want to redirect to your NotFoundPage component.

You should show something while the data loads. Just freezing your app entirely while some async side effect resolves doesn't make for a good UX. Your components should be able to show a "loading" view of some sort to give the user feedback while it's working.

Is there any way to solve this not using onEnter?

I'm using Firebase and it uses a token in local storage to sign the user in (or out if the token is not present). This takes a second or two and I want react-router to wait for this to happen before displaying any route.

Is this possible?

Edit: I've asked this on StackOverflow if anyone can/wants to answer ;)

This is how I have solved it for the time being.

https://gist.github.com/PierBover/220b2f7d5f790158790d3adb55f0a140

A rudimentary approach that does the job in case you are desperate for a solution as I was.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexyaseen picture alexyaseen  Â·  3Comments

andrewpillar picture andrewpillar  Â·  3Comments

wzup picture wzup  Â·  3Comments

sarbbottam picture sarbbottam  Â·  3Comments

winkler1 picture winkler1  Â·  3Comments