I am going through the documented pattern for structuring application state:
https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape
There one sees the following suggested way of maintaining the posts of a hypothetical blogging application:
posts : {
byId : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
},
allIds : ["post1", "post2"]
}
It is not at all clear to me what is the benefit of maintaining the allIds
field on that state. Doesn't the following data structure contain the exact same information?:
posts : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
}
The way I see it, the first approach (i.e. the officially suggested one) has redundant information which is normally seen as a defect. The only benefit of the first approach that I see is in case we are using the byId
property to cache some posts in advance. I am sure the official redux documentation has valid reasons for suggesting this pattern. I have used Redux in a few React apps but nothing too complex so I must be clearly failing to see something.
As it turns out, having connected parent components simply pass item IDs to connected children is a good pattern for optimizing UI performance in a React Redux application, so keeping state normalized plays a key role in improving performance.
A normalized state is a way to store (organize) data. With this way each entity type will have its own place in the store, so that there is only a single point of truth. This practice is the recommended way to organize data in a Redux application as you can read in the Redux recipes.
For maximum rendering performance in a React application, state should be stored in a normalized shape, many individual components should be connected to the store instead of just a few, and connected list components should pass item IDs to their connected child list items (allowing the list items to look up their own ...
The state can only be changed by emitting an action. The state tree is never mutated directly instead you use pure functions called reducers. A reducer takes the current state tree and an action as arguments and returns the resulting state tree.
The allIds
field has a couple benefits:
Object.keys(state.posts)
creates a new array every timeOur official Redux Toolkit package now has a new createEntityAdapter
API that implements the logic for managing this kind of normalized state shape, which it organizes as {ids: [], entities: {} }
. It specifically implements the ability to keep the ids
array in sorted order, and ensures the ids
array only changes when items are added, removed, or the sort order changes.
You might also want to read through Advanced Redux Entity Normalization, which has further thoughts on the use of ID arrays to indicate filtering and sort order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With