Blog>
Snippets

Normalize Redux State Structure

Showcase the transformation of a deeply nested object into a normalized state shape for a Redux store with entities and IDs.
import { normalize, schema } from 'normalizr';

// Define your comments schema
const comment = new schema.Entity('comments');

// Define your users schema
const user = new schema.Entity('users');

// Define your articles schema
const article = new schema.Entity('articles', {
  author: user,
  comments: [comment]
});

// Example of a nested data similar to what an API might send
const apiResponse = {
  articles: [
    {
      id: 'article1',
      author: {
        id: 'user1',
        name: 'User 1'
      },
      title: 'My awesome blog post',
      comments: [
        {
          id: 'comment1',
          content: 'Great post!',
          author: {
            id: 'user2',
            name: 'User 2'
          }
        },
        {
          id: 'comment2',
          content: 'Informative read.',
          author: {
            id: 'user3',
            name: 'User 3'
          }
        }
      ]
    }
    // ... other articles
  ]
};

// Normalize the nested data
const normalizedData = normalize(apiResponse, { articles: [article] });
This code snippet uses the normalizr library to normalize a deeply nested object. The 'schema.Entity' defines schemas for comments, users, and articles. Each article contains an author and an array of comments, and each comment contains an author. The normalize function converts the complex nested data into a flat shape with entities and IDs, suitable for use in a Redux store.
// Assuming a normalized state shape,
// an example Redux reducer to handle adding a received normalized payload.
function entitiesReducer(state = { users: {}, articles: {}, comments: {} }, action) {
  switch (action.type) {
    case 'RECEIVE_ENTITIES':
      return {
        ...state,
        users: {
          ...state.users,
          ...action.payload.entities.users
        },
        articles: {
          ...state.articles,
          ...action.payload.entities.articles
        },
        comments: {
          ...state.comments,
          ...action.payload.entities.comments
        }
      };
    default:
      return state;
  }
}

// Dispatch action with normalized data
// dispatch({ type: 'RECEIVE_ENTITIES', payload: normalizedData });
This snippet shows a Redux reducer that manages the state of entities such as users, articles, and comments. It takes an action 'RECEIVE_ENTITIES' that includes a normalized payload, and updates the state by merging the existing entities with the new ones from the action's payload. A dispatch function is hinted at the end, to show how you would send the normalized data to the reducer.