James Gillmore
Jul 23, 2017 · 3 min read

Good catch. ..The thing about the isLoading use here is that it’s in TransitionGroup, so it will correctly only apply to the current page, where’s the other page sliding away will use the old props. So yea, to serve lots of pages would require being responsible for a lot of pages.

However, that’s no difference to the correct/recommended/idiomatic use of reducers in RFR, where (as you probably saw in this article) reducers do more “tear down” work and you use less actions, i.e. less usage of actions as “setters.”

So you could just make one isSwitcherPageLoading reducer that — like what’s recommended for all reducers — responds to a bunch of actions to produce that boolean value. Then in the View layer (or rather, the “containers”), less work is going on. That’s probably the best as it means less duplication in the components that comprise your UniversalComponent.

The other option is to render the same loading component in each and every of those dynamically imported components. If they return the loading component as the one and only thing it returns until the data is ready, it will almost be seamless to the end user. It may in fact appear seamless, and if that’s the case, it’s a fine solution. It depends on how much animation you’re doing. The thing is that in this case, there will be an additional render that occurs. Here is the original render update sequence:

  • loading… (while chunk loads and while data loads)
  • re-render to show dynamically imported component

Here’s the new sequence:

  • loading… (while chunk loads)
  • loading… (as returned from dynamic component while data loads)
  • re-render to show the stuff you actually want to render within the dynamic component

So the latter would produce a more standard approach, with the caveat that it requires a lot more repeating yourself within components.

Imagine the second approach with a spinner — the key question is does that spinner drop a frame or restart its 360 degree spinning cycle when it’s in the middle of the cycle, say at 270 degrees (or 42% or whatever). That’s less than ideal, and what would occur with something like React Loadable that doesn’t concern itself with other things that might need to be loaded. And it’s basically all but guaranteed, but there’s probably plenty of cases where you don’t care.

….so I did the recommended approach of putting it in a reducer, and it came out great:

Let me know what you think. I’m gonna update my demos and the articles, cuz this is way better than having an additional state-related helper function in/near the View layer. Tho, there are cases where you wouldn’t have all the state in one reducer, in which case using a Reselect in the “Container Layer” is what you would do. This approach is basically what I did in the original minus example without Reselect. …The original approach is fine, and if you’re pulling state from multiple reducers to produce your answer, you gotta do it in a selector. That’s the bottom line. And it’s more performant for doing so, since reselect will memoize it. Selectors are just an extension of your reducers — a very smart extension that has access to all your reducers.

And to address your last point regarding race conditions, it’s handled within the reducer. Not all race conditions need a fancy solution. Probably the majority of the time you can handle them by the heuristics of your application, i.e. its data structures and desired user experience.

In this example we expect the category to be the same when going from LIST to VIDEOS_FETCHED. If it’s not, by the nature of the user experience, we know the user clicked the tabs too quickly, and therefore another VIDEOS_FETCHED will soon be received, and only that one should set isLoading to false. Similarly, the category shouldn’t be temporarily put back to the intermediary category you quickly skipped over :)

…One final thing: the new solution doesn’t in fact solve the problem where multiple pages are used that have their own loading i just realized. I simply pushed the code completely out of the view layer. Basically to do this with multiple reducers maintaining different loading states for different sections of your site, you gotta use Reselect — and again, that’s basically still your “Model” layer. People just happen to put them near components. I’ve have had apps with selectors folders. So basically just take the key aspects of this code, imagine you have 2+ reducers that would do this, do it in a selector instead, and combine the page reducer to determine the final isLoading state. That’s how to do this at a high level for real apps.

James Gillmore

Written by

http://www.faceyspacey.com + http://twitter.com/faceyspacey

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade