Updating nested data in redux store

Jonny’s answer is correct (never mutate the state given to you!) but I wanted to add another point to it. If all your objects have IDs, it’s generally a bad idea to keep the state shape nested.

This:

{
  items: {
    1: {
      id: 1,
      links: [{
        id: 10001
      }]
    }
  }
}

is a shape that is hard to update.

It doesn’t have to be this way! You can instead store it like this:

{
  items: {
    1: {
      id: 1,
      links: [10001]
    }
  },
  links: {
    10001: {
      id: 10001
    }
  }
}

This is much easier for update because there is just one canonical copy of any entity. If you need to let user “edit a link”, there is just one place where it needs to be updated—and it’s completely independent of items or anything other referring to links.

To get your API responses into such a shape, you can use normalizr. Once your entities inside the server actions are normalized, you can write a simple reducer that merges them into the current state:

import merge from 'lodash/object/merge';

function entities(state = { items: {}, links: {} }, action) {
  if (action.response && action.response.entities) {
    return merge({}, state, action.response.entities);
  }

  return state;
}

Please see Redux real-world example for a demo of such approach.

Leave a Comment