React Redux: Organisation, Data Immutability & Normalization

Jedidiah Amaraegbu
4 min readDec 24, 2020

This article is a summary of the following articles:

It answers the following questions:

  1. How should the Redux state be organized in Redux applications?
  2. Where is the concept of data immutability applicable in React?
  3. What does state normalization mean?

How should Redux state be organized in Redux applications?

Redux state should be organized based on the performance need of the app.

Recommendations for managing state is to use sub-stores and slice reducers that handle just a slice of the general state.

A user triggers a command, an action creator handles that command by dispatching a single action or multiple actions. These actions can be accessed from React components by using react-redux mapDispatchToProps function

These actions are then handled by their specific slice reducer which updates the sub-store they are concerned with.

To get back the data from the Redux store, selectors are used in the react-redux mapStateToProps function

Indexing

An index is a javascript object in which the keys are the ids of the data objects we’re storing, and the value is the actual data objects themselves.

Indexing helps save time and simplify retrieval code.

For example, an array of users received from the DB stored as an object where each key is the id of each user.

That way we don’t have to map over the array to find or update a user

https://gist.github.com/1c18a7110f6d368605e2f377e57f2617

Selectors

This is a function that takes in state and returns the required data

https://gist.github.com/68ed9ea0976570ab5da98772f74fcaea

By using selectors, we increase code maintainability

Consider using reselect for selectors

It is best to keep data retrieved from API calls, canonical state separate from data being edited by the user, view state. This way, should the user start say, editing his profile details, and in between cancel the edit:

  • the state of that edit is saved in the view state and can be retrieved later one
  • the data received from the API call does not change in the state until the user saves the changes

An example of a separate view and canonical state is shown below

https://gist.github.com/dc1f6be0f8664e589ce89f8aa963628b

A simple rule of thumb to use is:

  • Do other parts of the application care about this data?
  • Do you need to be able to create further derived data based on this original data?
  • Is the same data being used to drive multiple components?
  • Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
  • Do you want to cache the data (ie, use what’s in-state if it’s already there instead of re-requesting it)?
  • Do you want to keep this data consistent while hot-reloading UI components (which may lose their internal state when swapped)?

Where is the concept of data immutability applicable in React?

The concept of data immutability is applicable in the redux store state.

Here, the state cannot change its value except by calling action events.

These action events are then handled by reducers who do not change the state but returns a new state from the old one

What does state normalization mean?

It is the recommended approach to managing relational or nested data in a Redux store.

  • Each type of data gets its own table in the state
  • Each data table should store the individual items in an object, with the IDs of the items as keys and items themselves as values
  • Any references to individual items should be done by storing the item’s ID
  • Arrays of IDs should be used to indicate ordering

The major benefit of normalizing state data is improved performance, as it ensures the following:

  • Changes in multiple places are prevented as each item is only defined in a single place
  • The reducer logic is simpler as it doesn’t have to deal with different levels of nesting
  • The logic for retrieving or updating a given item is fairly consistent and straightforward.
  • Lesser portions of the state tree are required for state update

All relational should be under a parent key called entities

For relational tables that are being edited, the current edit can be stored under a parent key called work_in_progress, while the current data remains.

When the changes in the work_in_progress have been submitted, then the data in current is updated and that in work_in_progress is cleared

These tables can apply many of the principles of database design. For example, the join is shown below:

https://gist.github.com/50cc023004a7ef5d626e8bb58325bee3

Refer to normalizr for normalizing nested API data

Originally published at http://github.com.

--

--

Jedidiah Amaraegbu

Collaborating to bring ideas to life | Software Engineer | PostgreSQL, MongoDB, Node, Express, React, Redux | What’s your idea? 😏😏