React Redux: Immutable JS

As we all probably know by now, Javascript was not built with immutability in mind. For this reason, in our reducers, we usually copy over the state using object.assign or a spread operator to copy over the current state to a new state and append to it. This method is ok UNLESS our state is very big. In big apps, when we continue appending to our state in a session, our state keeps growing and growing, keeping data we no longer need. This is where immutable JS comes in. Two main persistent immutable data structures that immutable js offers are Map (for objects) and List (for arrays).


npm install --save immutable

Object/Array vs Map/List


Javascript Object:

const obj = {name: 'Rochelle', surname: 'Cassar', parents: {mother: 'Pauline', father: 'France'}} //Rochelle
obj.parents.mother //Pauline = 'Rochelle Claire'

Immutable JS Map:

const obj = Map({name: 'Rochelle', surname: 'Cassar'})

obj.get('name') //Rochelle
obj.getIn(['parents','mother']) //Pauline
obj.set('Rochelle Claire')


Javascript Array:

const arr = ['Rochelle', 'Cassar']

arr[0] //Rochelle
arr[0] = 'Rochelle Claire'

Immutable JS List:

const arr = List(['Rochelle', 'Cassar'])

arr.get(0) //Rochelle
arr.set(0, 'Rochelle Claire')

In order to avoid an extra learning curve, immutable JS lists have all the normal Array methods you’re used to like size, push, pop, includes, reverse and unshift.


toJS helps us changing an immutable JS Map/List to a plain javascript object/array accordingly.


On the contrary, fromJS helps us changing a plain javascript object / array to immutable JS Map/List.


Immutable JS uses merge to merge objects together:

const objFirst = {name: 'Rochelle'}
const objSecond = {surname: 'Cassar'}
const obj = objFirst.merge(objSecond)

Immutable Reducer States


import { Map, fromJS } from 'immutable'
const initialState = Map({
  isFetching: true,
  error: '',

export default function users (state = initialState, action) {
  switch (action.type) {
      return state.merge({
        isFetching: true
      return state.merge({
        error: '',
        isFetching: false,
        users: action.users
    default :
      return state

In Container:

Since immutablejs has a different way of accessing properties, we need to also make sure that our mapStateToProps is using .get instead:

function mapStateToProps ({users}, props) {
  return {
    user: users.get(props.uid)


If you use chrome redux extension or place a debugger in the mapStateToProps before the return, you can see that the state is always clean, consisting of the initialState plus the state we append in the reducer action. This was, any old state we do not need, is cleared out.