redux normalized state: byId and allIds pattern

Viewed 1536

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.

1 Answers

The allIds field has a couple benefits:

  • It provides a consistent array reference for "all IDs", whereas something like Object.keys(state.posts) creates a new array every time
  • It can act as a default sort order for all the items, whether it be based on insertion order or something else.

Our 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.

Related