2

I've seen numerous examples about this, but every example incorporates details about persistent values like todo is "completed". I understand we should keep this ("completed") value in store for each TODO, and when store gets recomputed using reducers, the component is re-rendered.

Where do we keep information like "isUpdating" etc for each todo, which I would use to show a loader on a particular todo item (not for the list of todos) when user marks a todo complete and a subsequent ajax call is involved to mark todo as complete in database.

I also understand that as this information might not be useful for other components I should better keep it under the presentational component "TODO". But if these flags are kept in the component, how will the component know that the update on todo was successful or failure on store update ?

2 Answers2

1

In redux we have multiple reducers that handle state as whole. In a todo app, todos are a slice of the state, but they are not always the entire state. In your case, your app's state consists of two entities, the todos, and the status of the loading.

With the above in mind, you can have one reducer that handles the todods. It will take care of loading all the items, or updating an item, or deleting one. In other words, this reducer is only concerned with the state of the todos, but it does not care about where you are in your lading process of an ajax call.

For the loading process you can create another reducer. This reducer knows nothing about your todos and it can really work for any sort of data that your app manages. All this reducer is worried about is if we are currently in the middle of an async ajax call. If we are then we can set some bool like isLoadingto true, and when the async call is either done or errored out we just set it to false. Then any component that wants to display some spinner while loading only needs to subscribe to state changes of this loading reducer.

This is the way I have implemented this feature in multiple production projects at my work. This is by no means the only way, or the best way, its just a way that I know works.

EDIT: The above works well for a more general loader across the site, however the OP wants to know how to make each individual item show a loader when some async call is happening that involves only that item.

The approach I would take is as follows. Instead of having only one array in state that keeps track of the todos, we now have 2 arrays in state. One array keeps track of the data, and the other keeps track of the data as it relates to UI. In other words, the array that keeps track of data will know nothing about isLoading since this is a UI related prop, but the other array will keep track of all the todos as they relate to UI. This way when looping through each todo during the render faze, we can look to see what the isLoading status is of this exact todo in the UI related array in state, and if isLoading is true then we display a spinner on this specific todo.

This gives a nice seperation of concerns. The array that is keeping track of data does not need to worry about UI at all. but we still get the benefit of having an individual spinner for item in the list.

Chaim Friedman
  • 6,124
  • 4
  • 33
  • 61
  • Im not concerned about the global loader here, as it may make sense to keep it on the top level state, Im interested in the nested TODO component, where should I keep the 3 states of an ajax call for a single TODO, I haven't seen any example that speaks about this. – Hardeep Singh May 03 '17 at 03:02
  • I actually had a talk with some of my co-workers regrading your question, and the general consensus was to include the isloading as a prop on the todo. There was another way that I thought of which I will update my answer to talk about it. – Chaim Friedman May 03 '17 at 03:04
  • So for every ajax call we need to have isLoading, isLoaded, isErrored props for a state slice in the state, seems like a lot of ephimeral state slices entered in global state, and where do we keep the info that some error occurred while updating a single item in the list. – Hardeep Singh May 03 '17 at 03:10
0

If you want to use redux middleware for handling these asynchronous action (such as redux-saga that you have tagged your question with) then it is much easier to store the values alongside the relevant items in the state.

Basically, it boils down to this: If you've externalised the action from the component, then you should externalise the resulting state of the action.

Michael Peyper
  • 6,814
  • 2
  • 27
  • 44
  • I get your point, so given a scenario that I can individually update a TODO and keeping the presentational/container component idiom in mind, should I convert each TODO to a container component with state {todo, isUpdating, isUpdated, isErroneuos} ? I understand I should ask another question, but this seems connected. – Hardeep Singh May 03 '17 at 03:06