Immutable Redux

In this lesson, we will use Immutable.js in our Weather app that's created using React and Redux

we make the initial state in our reducer an immutable object by using the fromJS function! We simply wrap the object that we assign to initialState in fromJS like so:

// reducer.js
/* … */
import { fromJS } from 'immutable';

var initialState = fromJS({
  /* … */
});

/* … */

Now we need to rework our reducer. Since our state is now immutable, instead of doing Object.assign({}, state, { /* … */ }) everywhere we can simply use state.set!

Let’s showcase this on the CHANGE_LOCATION action. This is what our reducer looks like right now:

case 'CHANGE_LOCATION':
	return Object.assign({}, state, {
	  location: action.location		
	});

Instead of doing this whole assigning business, we can simply return state.set('location', action.location)!

case 'CHANGE_LOCATION':
	return state.set('location', action.location);

Not only is that a lot cleaner, it’s also forcing us to work immutably, which means we can’t accidentally mess something up and introduce weird bugs! 🎉

Let’s do the same thing for our SET_DATA, SET_DATES and SET_TEMPS cases:

case 'SET_DATA':
  return Object.assign({}, state, {
    data: action.data
  });
case 'SET_DATES':
  return Object.assign({}, state, {
    dates: action.dates
  });
case 'SET_TEMPS':
  return Object.assign({}, state, {
    temps: action.temps
  });

This whole block becomes:

case 'SET_DATA':
 return state.set('data', fromJS(action.data));
case 'SET_DATES':
 return state.set('dates', fromJS(action.dates));
case 'SET_TEMPS':
 return state.set('temps', fromJS(action.temps));

Isn’t that nice? Now, here’s the last trickery in our reducer, because what do we do for SET_SELECTED_TEMP and SET_SELECTED_DATE? How do we set state.selected.temp?

It turns out Immutable provides us with a really nice function for that called setIn. We can use setIn to set a nested property by passing in an array of keys we want to iterate through! Let’s take a look at that for our SET_SELECTED_DATE.

This is what it currently looks like:

case 'SET_SELECTED_DATE':
  return Object.assign({}, state, {
    selected: {
      date: action.date,
      temp: state.selected.temp
    }
  });

This works, but you have to agree it’s not very nice. With setIn, we can simply replace this entire call with this short form:

case 'SET_SELECTED_DATE':
  return state.setIn(['selected', 'date'], action.date);

So beautiful! Let’s do the same thing for SET_SELECTED_TEMP and we’re done here!

case 'SET_SELECTED_TEMP':
  return Object.assign({}, state, {
    selected: {
      date: state.selected.date,
      temp: action.temp
    }
  });

becomes

case 'SET_SELECTED_TEMP':
  return state.setIn(['selected', 'temp'], action.temp);

This is what our reducer looks like finally (let’s try running our weather app with our new reducer):

Get hands-on with 1200+ tech skills courses.