Search code examples
reactjsflux

Flux and React: how show a loading indicator when the requests from my app are made? The good, the bad and the ugly try


I'm trying to figure out the best way to hide/show the loading indicator when I'm doing a request.

I have a:

  • LoadingAction to emmit an event to show/hide the loading indicator.
  • LoadingStore to hold the loading information (show/hide).
  • loading.jsx: the loading indicator component.

I tried different things to do that in the "flux way":

  • good: call a LoadingAction.showLoading() before the request and LoadingAction.hideLoading() when the response arrives.
  • bad: call a LoadingAction.showLoading() in each view that call an action (that made a request) and LoadingAction.hideLoading() when my callback is called from the Store.
  • ugly: I tried to change the LoadingStore directly with a setter method (what is not the right solution...) when I made the request and receive the response.

But, except for the last try (the "ugly"), I always receive the error dispatch in the middle of a dispatch.

I'm aware that what this means but I can't think in another strategy.

I don't want to use setTimeout function to resolve this problem. This is not the right solution.

Thanks!


Solution

  • After some time, we end up with the solution described here. The approach was very different than my original idea: each component take cares about the loading, like this:

    render: function(){
       // while loading
       if (!this.state.data){
         return <Loader/>
       }
    
       // loaded, you can use this.state.data here
       return <div>...</div>
    }
    

    But, we have problems when an API return an error. How the component can remove the <Loader /> in this case?

    Well, each component with need to register and listen (we use Flux) the dispatch from our promise based HTTP client (Axios). Like this:

            componentDidMount: function(){
                LoaderStore.addChangeListenerEsconderLoading(this.stopLoading);
            },
    
            componentWillUnmount:function(){
                LoaderStore.removeChangeListenerEsconderLoading(this.stopLoading);
            },
    

    And this (using Axios):

    request(options)
      .then(function(response){
        success && success(response.data);
       })
       .catch(function (error) {
         LoaderAction.hideLoading();
      }