Nov 30, 2021 . 3 min read

Normalizing Redux Store

Ever feel that checking or retrieving certain data from your redux store is a hassle? Now is the time to check if you did normalize your redux store to help reduce data redundancy as well as improve its performance.


What is normalization?

Normalization is the process of restructuring the storage by making the data more efficient by reducing redundancy and flattening the structure. This is usually achieved by changing the schema of the storage. In fact, the idea of normalizing redux store is akin to database normalization which has the goal of reducing data redundancy and improving data integrity. If you’re familiar with terms like 1NF, 2NF, BCNF, etc, then the idea of redux store normalization shouldn't be foreign.

Issues with un-normalized data

  • Even if the data did not change, a modification to a deeply nested data object might cause unrelated UI components to re-render and this behavior is highly undesirable.
  • With a nested structure, it will make updating and accessing fields difficult, which will result in the reducer being very complicated.
  • It’s more difficult to ensure that data is updated effectively when it’s replicated in several places.

Since many applications use data that is nested or relational, and usually when the data received is in a nested JSON format, if we simply store the data as it is from the endpoint, sometimes we will face issues with accessing or even updating certain data.

What are the benefits of normalizing our data?

  • With reduced or removed duplicate data, we can achieve single source of truth for certain data. You only have one source of data in the store and will be the source for many parts to access.
  • Lesser memory usage in store.
  • No complex reducers for updating and acessing certain data.
  • Improved performance.
  • The data type is separated, thus updating certain field would only require new copy of that portion of the tree(store). This will mean fewer components of the UI will need to be updated or re-rendered when the data is changed.

Some use cases, whereby normalization comes in handy, are twitter’s tweets where each tweet has multiple comments, likes, reposts by multiple users, and usually, such data comes in nested JSON format. Also, we can think of an e-commerce perspective whereby getting information about certain orders, will include shop IDs, shop details, item IDs, item details and etc.

Example

Let's look into a simple example of how our normalizing helps to improve our redux store. Imagine we fetch some data via the API from the backend and it is nested. Take for example get_shop_orders returns to us data that is formatted as such:

{
  "shop_orders": [
    {
      "shop_id": "shop_1",
      "items": [
        {
          "item_id": "item_a",
          "price": 11.30
        },
        ...
      ],
    },
    {
      "shop_id": "shop_2",
      "items": [
        {
          "item_id": "item_a",
          "price": 11.30
        },
        ...
      ],
    },
    ...
  ],
}

If we just want to save this result straight into our store, when we want to update a certain item lets say item_a, it will be difficult at first, and in the worst case, we will have to go through all the shop orders, and also go through each of the items and update them individually. This is a costly operation and also requires us to be careful in updating all the correct item. Also notice that we now have multiple source regarding item_a which could result in inconsistent data if updated incorrectly.

Now lets see how a normalized store could ease our update of data and also remove data redundancy and ensuring a single source of truth regarding item_a.

{
 "shop_orders": {
    "shop_1": {
      ...shop_information,
      "items": ["item_a", ...],
    },
    "shop_2": {
      ...shop_information,
      "items": ["item_a", ...],
    },
    ...
 },
 "item_map": {
    [item_id]: {
      ...item_information,
    },
 },
}

 

Note that item_id is notation similar to mapped types in typescript

Now if we want to update item_a , all we have to do is access the item_map and update the key which is item_a and all shop_id that have reference to item_a will be updated correctly because they are just referencing the key. Also, we now only have one source of all the items thus we removed the duplicate data that are referring the the same item.

Conclusion

All in all, data received from backend are usually in nested JSON formats and we shouldnt have to deal with this nested format in our redux store. We can go with properly designed schemas that are better optimised for read performance and store storage.

If normalizing the store is abit of a painful process, fret not! There is a library called normalizr which can help to faciliate the process.

I hope you enjoyed this introduction of using a normalized state in a Redux and hope that you are able to apply this technique when you’re designing on your Redux store schema.

Image credits to Unsplash

View Medium article here


© Made with passion - Sean Lum 2022