3

I have a React app that uses Redux with redux-thunk. Given a certain component that needs to fetch information from an API, I call a bound action creator to make that request after it mounts:

componentDidMount() {
  this.props.fetchSomething();
}

For the UI to know whether it is in a loading state, I use a loading variable from the application state. My reducer handles three action types for LOADING, SUCCESS, and FAILURE. The loading variable is set to true when the LOADING action is emitted; then it is set to false on SUCCESS and FAILURE.

Thus there is the following in the render method:

render() {
  if (this.props.loading) {
    return <Spinner />;
  }

  return (
    <div>
      This part uses the fetched data, available via this.props.something
    </div>
  );
}

Because initially this.props.something is null, I also have to check for its existence before rendering the desired template, so the above if-statement becomes:

if (!this.props.something || this.props.loading) {
  return <Spinner />;
}

This approach has served me well so far, but there are some issues, one of them being:

The first time I access the page, this.props.something is not yet set. But the second time I access the page, with the app already loaded, that data had already been fetched once, so this.props.something will have been defined. Because of that, there is brief moment in which the if statement condition is FALSE and the actual component template gets rendered.

(1) How would you guys take care of that issue?

(2) And with your approach, how would you handle a component that had to make multiple requests, like five of them, using the same approach above, with a different loading/something variable for each? I can duplicate the same approach above, but get the issue of brief if-statement failure for each resource that is already defined, but not loading.

nbkhope
  • 7,360
  • 4
  • 40
  • 58

1 Answers1

1

1) You have two options. U can dispatch some RESET action on componentWillUnmount and reset your store, this.props.something will be null again. Second option is to show data if u already have them, show spinner and when second fetch is success merge it together. (depends on purpose and UI)

2) I have never needed it but what about to store it in redux as map {componentName: loaded} and check if all components are loaded?

Edit: When u set initial value of loading to true you don't need to check something prop.

  • a) I had loading set to false by default. I think initializing it to true is something to think about. b) I used to use componentWillMount for http requests, but then stopped using it and now use componentDidMount, because I was told / read somewhere that was the best practice. It would be nice to have someone confirm that. c) Regarding (1), I could do that, but I use reducer composition and the multiple resources are split between different subreducers. In that case, I would have to make a reset for each? – nbkhope Nov 08 '17 at 22:25
  • The issue I am trying to solve has to do with the spinner. The brief moments when each resource is already set, but not loading causes the if statement in the render to skip rendering the Spinner and going all the way through. That is barely seen by the end user, but the spinner clearly goes back to its initial animation state, it looks weird. – nbkhope Nov 08 '17 at 22:27
  • a) i call it `loaded` to make it logically sense b) sorry `componentDidMount` is better, explanation: [where-fetch-data](https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/) c) here is example how to reset state after logout: [how-to-reset-the-state](https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store) – Miroslav Papírník Nov 09 '17 at 10:28
  • To the issue what about to not handle spinner on the top level, but in children components and instead of spinner use some kind of preloaders? (e.g. empty div with approx same size, so user will see approximate layout) – Miroslav Papírník Nov 09 '17 at 10:32
  • 1
    Thank you for the insight. I ended up calling many action creators to reset the resource variable to null in componentWillUnmount. I found that was the best approach for what I was trying to do. As for handling the spinner in the children, that sounds like a good approach too, but my specification needs the whole page to be under the spinner. – nbkhope Nov 09 '17 at 17:51