Consider the Todo List example, if I want to create multiple TodoLists, one for each work, home personal and grocery, then the actions and the reducers would need to know which TodoList am I talking about every single time I want to use them. This can still be easily solved by dynamically creating these actions, the real problem arises when the reducer are mutating the states.
The state of each of the TodoList would be different and one would have to create some sort of a namespace in the global store to differentiate between them. Is there are more cleaner way of solving this problem?
You could create one big array of todo objects and give each item a "category" property for work / home / etc, besides the name/label of the todo. The currently active/selected category could be a variable in the store and used to know what category to set on newly created todo's in the reducer function.
In your list rendering you would use this category to filter the array for the relevant todo items to show.
This way you can create an arbitrary number of categories easily.
@0x80 I really appriciate your answer, but it seems too specific to the current example. What if I want to persist the state of filters (completed, active, all) independantly for each todo list?
@tusharmath I don't quite understand you. Add category as a property to each todo item. When you want to show only home + completed filter on those two properties. Category would just be an extra filter that you use to display the items from one of your lists. You can use multiple properties to for example show only the completed items in the home list
I didn't look at the todo example before, but I see it is already an array of items (which makes total sense). So you can add category as a property to each item and in the store create a variable to keep track of the selected category, and you should have enough information to display/edit any number of lists.
What I meant was: I want to save the states of these todo lists ie. the selected filters and the data, in a global store.
You could have a "shape" reducer similar to this.
Normally it's used for the same purpose as combineReducers, but you could also make it so that you could attach an id for a new todo list, and then assign the todo list reducer to it. All you need to do then is to make sure the right action goes to the right reducer.
Had I create a state for each component, I wouldn't have to manually handle this at all right ? Worrying about ids and passing them to reducers?
You mean directly modifying the state from the component? That's not redux anymore.
I agree, that its not redux, but is it like the cost one need to pay for all the gains we get from a single store?
I mean, the whole point of flux is to sacrifice a bit of convenience for maintainability and scalability.
You probably want to look over the docs on state shape again. You'll also probably find some use with normalizr to give you better access to your state data in a shape that's scalable.
Also, if you kept state on a per-component basis, you wouldn't be able to do things like have a counter of the number of incomplete todos in your header. A single store means there is a single source of truth in your app, and therefore no conflicting states in your app.
We can assume another case, which seems like the multiple TodoLists, but it's hard to avoid by a better design of state tree:
We have a SPA application consists of a profile page and a followerList page. The state tree is as shown in the following:
{
profile: { name: xx, sex: xx, followers: 123 },
followerList: []
}
We can open a follower list page from a profile page A, and then open a profile page B from the follower list page. In my application, page A and page B share the same reducer profile.
Here is the problem: when page B rendered, the profile in state tree has been changed by B's info; when it returns back to page A, it is supposed to keep A's info, but it has also been rendered by B's info.
How can we solve this problem?
@malcolmyu for your particular case, i think when ever you go to a profile page an http request needs to be made to get that particular profile data.
@tusharmath It means that I have to refresh the profile page even if just returning back to it. In my option, it's not an elegant way in a SPA hybrid application.
@malcolmyu You can always cache that response with a different Service layer. Having all the responses saved in the store won't be a really good idea, as it could cause memory leaks.
@tusharmath Thank you for your advice, and I will give it careful reconsideration.
I had the same problem as @tusharmath. I ended up writing the following reducer enhancer
Good Concepts: NameSpaced Instances
Is there a new approach for this issue?
Most helpful comment
Good Concepts: NameSpaced Instances