Redux First Steps: Shotgun Episode 5

Midnight Cowboy — Brandon Bailey (CC-BY-2.0)
Shotgun is a video screencast show that lets you ride shotgun with me while I tackle real programming challenges for real apps and libraries. The show is only available to members of EricElliottJS.com, but I’m journaling the adventures here.

Catch up:

Getting Started

If you haven’t cloned the app yet, do that first:

git clone git@github.com:jshomes/course-player.git

Make sure your local copy is up to date, and then check out the starting point for this episode:

git fetch — all && git merge origin/master
git checkout episode-5-start
npm install

Then to run the testing console:

npm run watch

You should be all set now to follow along and see how the changes effect things in the browser and the unit tests at the same time.

Current Status

We’ve built out the basic course player UI, which walks users through a playlist of information cards, called a deck. Now it’s time to add our state management features, and for that, we’re using Redux. To learn more about Redux architecture, check out “10 Tips for Better Redux Architecture”.

Redux First Steps

The core building block of Redux is the reducer function. A reducer function is a function that gets applied to every element in a collection or stream in order to reduce the data to a single value — in this case, the application’s state.

Reducers take two arguments, the current state, and the data to be applied, and return the next state:

reducer(state, action) => nextState

In Redux, the reducer is the single source of truth for state, and it is responsible for determining its own initial state, so the first step to building a reducer is to determine the store shape and return the default state if the reducer receives no arguments.

I always start building reducers with a unit test to be sure that the reducer is returning the correct default state, but instead of hard-coding that state, I create a factory that I can call from any of the unit tests:

This way, I can reuse the factory to create whatever state I need for the test at hand. Another benefit of the factory is that if the state shape changes, I only have to change it in one place, instead of in potentially many unit tests.

Immutable State

Reducers must be pure functions (see “Master the JavaScript Interview: What is a Pure Function?”), meaning:

  1. Given the same arguments, always return the same value.
  2. No side-effects.

I have always liked the idea of using immutable data structures for application state, but after using reducers with teams, it became clear that accidental state mutations are fairly common, even with groups of smart developers.

I’ve recently started using Immutable.js more in reducers. I’m not really fond of the API, but I made some sugar called dpath to smooth over the rough edges.

Even with immutable state, you should still be careful not to mutate the action object or any shared mutable state outside the reducer.

Recap

Remember, reducers should follow some simple rules:

  1. Given no state, reducers should always return valid initial state.
  2. Reducers should be pure functions. You can use immutable data structures like Immutable.js to help you avoid accidental state mutation.

Members, watch the video.

Non-members, sign up now:

Learn JavaScript with Eric Elliott


Eric Elliott is the author of “Programming JavaScript Applications” (O’Reilly), and “Learn JavaScript with Eric Elliott”. He has contributed to software experiences for Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, and top recording artists including Usher, Frank Ocean, Metallica, and many more.

He spends most of his time in the San Francisco Bay Area with the most beautiful woman in the world.