React and Redux: Proper Way To Store Loading State in Redux

Viewed 3349

I have one file loading ui that I call whenever my app's components fetch data from the backend so the frontend can show loading... The issue is when one component is fetching data, I dispatch loadingData() which causes the other components to showing loading... as well. I know this is happening because I have one action for loading that I dispatch. My question is, should I have separate loading actions for each component? If no, how can I go about fixing this? Thank you.

//Loading action

export const LOADING_DATA      = '[ui] LOADING DATA';
export const LOADING_DATA_COMPLETE    = '[ui] LOADING DATA COMPLETE';

export const loadingData = () => ({
  type: LOADING_DATA
});
3 Answers

The answer is you shouldn't have a loadingData() Redux action in the first place. Loading or not is, as you correctly pointed out, every component's "local" state, so you should store it appropriately - inside each component's "normal" state.

Redux store is designed for storing the data that is mutual to several components. And whether some component is ready or not is certainly NOT that.

It is perfectly fine to handle a loading state either in local component state, the part of your redux state where you will finally store the data, or a completely different part. There is no "one size fits all" solution and different applications handle it differently.

If you want to track that state globally, it is a fairly common pattern to have a yourApi/pending action followed either by a yourApi/fulfilled or yourApi/rejected action - this is how createAsyncThunk of the official redux toolkit handles it.

But of course, if you have two components sharing the same data, then they also share the same loading state. Maybe you should check if the data is already present and fetch it only when it is not already present, because why fetch it twice in the first place? Or, if the loading state is really describing a different endpoint, really split that up into multiple loading state.

There is good practice that you have loading for each subject you're calling a backend api, for example a loading for calling books api, a loading for calling movies api and so on.

I recommend you create a loadings object in your state and fill it with different loadings that you need like this:

loadings: {
  books_loading,
  movie_loading
}

so in your components, you wouldn't call a general loading state which affects a lot of components, only those who need the specific loading will use it and you will solve the problem you have

Related