Learn Redux with Dan Abramov

Redux presents a sane and scalable way to manage complex state in your React applications.

Watch the Screencasts on egghead.io

In this comprehensive tutorial, Dan Abramov - the creator of Redux - will teach you how to manage state in your React application with Redux.

State management is absolutely critical in providing users with a well-crafted experience with minimal bugs.

It's also one of the hardest aspects of a modern front-end application to get right.

Redux provides a solid, stable and mature solution to managing state in your React application. Through a handful of small, useful patterns, Redux can transform your application from a total mess of confusing and scattered state, into a delightfully organized, easy to understand modern JavaScript powerhouse.

The principles of Redux aren't new, but they are packaged and presented for you in an easy to use library that not only elevates your applications, but also improves your general understanding of building JavaScript UIs.

In this course, Dan Abramov will show you the fundamentals of Redux, so that you can start using it to simplify your applications.

Dan Abramov

Dan Abramov works at Facebook on React

He is the co-author of Redux and Create React App

Table of Contents

Table of Contents

0. The Single Immutable State Tree in Redux

Watch this lesson

The first principle of Redux is whether your app is a really simple one like this counter example, or a complex application with a lot of UI, and change of state, you are going to represent the whole state of your application as a single JavaScript object.

All mutations, and changes the state in Redux are explicit. It is possible to keep track of all of them. In this case, I am logging every state change in the application in the console. You can see that, in the counter example, there isn't really much state to keep track of so it can be represented by a JavaScript number.

Numbers Showing State

Here is a different example, a list of independent counters that I can add and remove. In this case, a single number is not enough to represent the state of the application, so we use an array of JavaScript numbers. In a more complex application, there is more state to keep track of.

Multiple Counter State

This is a typical todo app, where I can add todos, I can cross them as completed ones, and I can change their current filter. Looking back at the history of the state changes, we can see that the initial state of the app was a JavaScript object, containing an array under the todo string, and a string seen show all, under visible filter.

ToDo App State

When I added the first todo, it was added to the todos array, inside our state object. The todo itself, is described by a plain child script object, saying it was not completed, and the text was saved. Every further change that the app, whether when I was crossing out the todos, or when I changed the visibility filter, resulted in this change to this state object, described in our whole application.

Now you know the first principle of Redux, which is that, everything that changes in your application, including the data and the UI state, is contained in a single object, we call the state or the state tree.

1. Describing State Changes with Redux Actions

Watch this lesson

The second principle of Redux is that the state tree is read only. You cannot modify or write to it. Instead, anytime you want to change the state, you need to dispatch an action.

An action is a plain JavaScript object describing the change. Just like the state is the minimal representation of the data in your app, the action is the minimal representation of the change to that data.

Describing Actions

The structure of the action object is up to you. The only requirement is that it has a type property, which is not undefined. We suggest using strings, because they are serializable.

In different apps, you're going to have different types of actions. For example, in a counter app we only have INCREMENT and DECREMENT actions. We don't pass any additional information, because this is all that is needed to describe these changes.

But say, for a counter list example, we have more actions. We have ADD_COUNTER action, we have a REMOVE_COUNTER action, and anytime I change the individual counter, you can see that the INCREMENT and the DECREMENT actions now have index. Because we need to describe which particular counter was changed.

Multiple Actions

This approach scales well to medium and complex applications. Anytime I add a todo, the components don't really know how exactly it's been added. All they know is that they need to dispatch an action with a type, ADD_COUNTER, and the text of the todo and a sequential id.

If I toggle a todo, again, the components don't know how it happens. All they need to do is to dispatch an action with a type, TOGGLE_TODO and pass in the id of the todo I want to toggle.

Complex Example

The same is true for the visibilityFilter. Anytime I click on this control to change the currently visible todos, what really happens is this component dispatches an action with a type, SET_VISIBILITY_FILTER, and pass in the desired filter string, filter field.

But these are all plain objects, describing what happens in a app.

Now you know the second principle of Redux -- the state is read only. The only way to change the state tree is by dispatching an action. An action is a plain JavaScript object, describing in the minimal way what changed in the application. Whether it is initiated by a network request or by user interaction, any data that gets into the Redux application gets there by actions.

2. Pure and Impure Functions in Redux

Watch this lesson

Before we proceed any further, it's important that you understand the difference between the pure and impure functions. The pure functions are the functions whose returned value depends solely on the values of their arguments.

// Pure function
function square(x){
  return x * x;
}

Pure functions do not have any observable side effects, such as network or database calls. The pure functions just calculate the new value. You can be confident that if you call the pure function with the same set of arguments, you're going to get the same returned value. They are predictable.

Also, pure functions do not modify the values passed to them. For example, squareAll function that accepts an array does not overwrite the items inside this array. Instead, it returns a new array by using items.map.

// Pure function
function squareAll(items){
  return items.map(square);
}

On the opposite, impure functions may call the database or the network, they may have side effects, they may operate on the DOM, and they may override the values that you pass to them.

// Impure functions
function square(x){
  updateXInDatabase(x);
  return x * x;
}
function squareAll(items){
  for (let i = 0; i < items.length; i++) {
    items[i] = square(items[i]);
  }
}

This is going to be an important distinction because some of the functions that you're going to write in Redux have to be pure, and you need to be mindful of that.

3. The Redux Render Function

Watch this lesson

You might have heard that the UI or the view layer is most predictable when it is described as a pure function of the application state. This approach was pioneered by React but is now being picked up by other frameworks, such as Ember and Angular.

The Reducer

Redux complements this approach with another idea, that the state mutations in your app need to be described as a pure function that takes the previous state and the action being dispatched and returns the next state of your application.

Inside any Redux application, there is one particular function that takes the state of the whole application and the action being dispatched and returns the next state of the whole application. It is important that it does not modify the state given to it. It has to be pure, so it has to return a new object.

Even in large applications, there is still just a single function that manages how the next state is calculated based on the previous state of the whole application and the action being dispatched. It does not have to be slow.

Large App Example

For example, if I change the visibilityFilter, I have to create a new object for the whole state, but I can keep the reference to the previous version of the todos state, because it has not changed when I changed the visibilityFilter. This is what makes Redux fast.

Now you know the third and the last principle of Redux. To describe state mutations, you have to write a function that takes the previous state of the app, the action being dispatched, and returns the next state of the app. This function has to be pure. This function is called the Reducer.

4. Writing a Counter Reducer for Redux with Tests

Watch this lesson

The first function we're going to write is the reducer for the counter example. Reducer accepts state and action as arguments and returns the next state. Before jumping into the implementation, we're going to make certain assertions using Michael Jackson's Expect library. We're going to assert that when the state of the counter is 0 and you pass an INCREMENT action it should return 1. Similarly it should return 2 when this state is 1 and you INCREMENT.

function counter(state, action){
  return state;
}

expect(
  counter(0, { type: 'INCREMENT' })
).toEqual(1);

expect(
  counter(1, { type: 'INCREMENT' })
).toEqual(2);

We're going to add a couple of tests that test how DECREMENT works, which is that it decrements from 2 to 1 and from 1 to 0 and we're going to add a log to tell if our tests are successful.

expect(
  counter(2, { type: 'DECREMENT' })
).toEqual(1);

expect(
  counter(1, { type: 'DECREMENT' })
).toEqual(0);

console.log('Tests passed!')

Tests Failed

If you ran this test, they're actually going to fail because we haven't even begun to implement our reducer. We're going to start by checking the action.type and if the action.type is INCREMENT we're going to return state + 1, but if it is DECREMENT we're going to return state - 1.

function counter(state, action) {
  if(action.type === 'INCREMENT'){
    return state + 1;
  } else if (action.type === 'DECREMENT') {
    return state - 1;
  }
}

If you run the tests we will find that this is enough to get them to pass. However, there are still some flaws in our current implementation of the counter reducer. For example, I think that if we dispatch an action that it does not understand, it should return the current state of the application.

expect(
  counter(1,{ type: 'SOMETHING_ELSE' })
).toEqual(1);

Tests Passed

However, if we check for that we will see that this test fails, because we currently don't handle unknown actions. I'm going to add an else clause that returns the current state. The tests pass now.

if(action.type === 'INCREMENT'){
    return state + 1;
  } else if (action.type === 'DECREMENT') {
    return state - 1;
  } else {
  return state;
}

Another issue is that while the reducer is normally in control of the application state, currently it does not specify the initial state. In the case of counter example that would be 0.

expect(
  counter(undefined, {})
).toEqual(0);

The convention we use in Redux is that if the reducer receives undefined as the state argument, it must return what it considers to be the initial state of the application. In this case it will be 0.

function counter(state, action) {
  if (typeof state === 'undefined'){
    return 0;
  }
}

Now come a few cosmetic tweaks. I'll replace this bunch of tweaks with a switch statement and I'm going to replace this condition with ES6 default argument, which looks better. I'm also going to replace the function declaration with an arrow function, which has clearer semantics in ES6.

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

5. Redux Store Methods GetState, Dispatch, and Subscribe

Watch this lesson

I added Redux to our application as a script tag from CDNJS. This is the UMG build, so it exports a single global variable called Redux, with a capital R. In real applications, I suggest you to use npm instead and a module bundler like webpack or Browserify, but the UMG build will suffice for our example.

I'm going to need just a single function from Redux called createStore. I'm using ES6 destruction syntax here. It's equivalent to writing, var createStore = Redux.createStore or, if you use NPM and something like Babel to transpile your ES6, you can write, import { createStore }, notice the bracers, from Redux.

const { createStore } = Redux;
// var createStore = Redux.createStore;
// import { createStore } from 'redux';

This store binds together the three principles of Redux. It holds the current application's state object. It lets you dispatch actions. When you create it, you need to specify the reducer that tells how state is updated with actions.

In this example, we're calling createStore with counter as the reducer that manages the state updates. This store has three important methods.

const store = createStore(counter);

console.log(store.getState());  // 0

The first method of this store is called getState. It retrieves the current state of the Redux store. If we were on this, we're going to see 0 because this is the initial state of our application.

The second and the most commonly used store method is called dispatch. It lets you dispatch actions to change the state of your application. If we log this store state after dispatch, we're going to see that it has changed.

store.dispatch({ type: 'INCREMENT' });
console.log(store.getState());  // 1

Of course, always log into the console gets boring, so we're actually going to render something to the body with the help of the third Redux store method, called subscribe. It lets you register a callback that the Redux store will call any time an action has been dispatched, so that you can update the UI of your application. It will reflect the current application state.

store.subscribe(() => {
  document.body.innerText = store.getState();
});

document.addEventListener('click', () => {
  store.dispatch({ type: 'INCREMENT' });
});

I'm being very naive now. I'm not using React or anything. I'm just rendering the counter into the document body. Any time the body is clicked, I'm going to dispatch an action to increment this counter.

If you pay close attention, you will notice that the initial state, the 0, was not rendered. This is because I'm rendering inside the subscribe callback, but it doesn't actually fire the very first time.

Subscribe Method

So I extract this logic into render method. I subscribe the render method to this store. I also call it once to render the initial state. Now it renders the 0, and the click increments the counter. This is our first working Redux application.

const render = () => {
  document.body.innerText = store.getState();
};

store.subscribe(render);
render();

6. Implementing Redux Store from Scratch

Watch this lesson

In the previous video we looked at how to implement a simple counter example using the createStore function provided by Redux and the store object it returns that provides the getState method to get the current application state, the dispatch method, to change the current application state by dispatching an action, and the subscribe method to subscribe to the changes and re-render our application with the current state of the app.

If you're like me you prefer to understand the tools that you're using. In this tutorial we're going to re-implement the createStore function provided by Redux from scratch. The first and the only form of what we know so far argument to the createStore function is the reducer function provided by the application.

We know that the store holds the current state. We keep it in a variable, and the getState function is going to return the current value of that variable. This function, combined with the dispatch function and a subscribe function on a single object is what we call the Redux store.

const createStore = (reducer) => {
  let state;
  let listeners = [];

  const getState = () => state;

  const dispatch = (action) => {

  };
  const subscribe = (listener) => {

  };
  return { getState, dispatch, subscribe };
};

Because the subscribe function can be called many times, we need to keep track of all the changed listeners. Any time it is called we want to push the new listener into the array. Dispatching an action is the only way to change the internal state.

const subscribe = (listener) => {
  listeners.push(listener);
};

In order to calculate the new state we call the reducer with the current state and the action being dispatched. After the state was updated, we need to notify every changed listener, by calling it.

const dispatch = (action) => {
  state = reducer(state, action);
  listeners.forEach(listener => listener());
};

There is an important missing piece here. We haven't provided a way to unsubscribe a listener. Instead of adding a dedicated unsubscribe method, we'll just return a function from the subscribe method that removes this listener from the listeners array.

const subscribe = (listener) => {
  listeners.push(listener);
  return () => {
    listeners = listeners.filter(l => l !== listener);
  };
};

Finally, by the time the store is returned we wanted to have the initial state populated. We're going to dispatch a dummy action just to get the reducer to return the initial value.

dispatch({}); // 5

This implementation of the Redux store apart from a few minor details and edge cases, is the createStore shipped with Redux.

7. Redux Counter Example

Watch this lesson

In the simplest counter example, I update the document body manually any time this tool state changes. But, of course, this approach does not scale to complex applications. Instead of manually updating the DOM, I'm going to use React.

I'm adding two scripts corresponding to React and react-dom packages and a root <div/> to render to. Now I can call the ReactDOM.render with my root component. The render function is called any time this store state changes, so I can safely pass the current state of this store as a prop to my root component.

const render = () => {
  ReactDOM.render(
    <Counter value={store.getState()} />
    document.getElementById('root')
  );
}

Since this state is held inside the Redux Store, the Counter component can be a simple function, which is a supported way of declaring components since React 14.

const Counter = ({value}) => (
  <h1>{value}</h1>
);

I want to add, DECREMENT, and INCREMENT buttons to the component, but I don't want to hard-code the Redux dependency into the component. So I just add onIncrement and onDecrement props as callbacks. In my render method, I pass the callbacks that call store.dispatch with appropriate actions. Now the application state is updated when I click the buttons.

const Counter = ({
  value,
  onIncrement,
  onDecrement
}) => (
  <div>
  <h1>{value}</h1>
  <button onClick={onIncrement}>+</button>
  <button onClick={onDecrement}>-</button>
  </div>
);

<Counter
      value={store.getState()}
      onIncrement={() =>
        store.dispatch({
          type: 'INCREMENT'           
        })            
      }
      onDecrement={() =>
        store.dispatch({
          type: 'DECREMENT'           
        })            
      }
    />

Let's recap how this application works. The counter component is what I call a dumb component. It does not contain any business logic. It only specifies how the current application state transforms into renderable output and how the callbacks, passed via props, are bound to the event handlers.

Counter Example

When we render a counter, we specify that its value should be taken from the Redux Store current state. When the user presses INCREMENT or DECREMENT, we dispatch corresponding action to the Redux Store. Our reducer specifies how the next state is calculated based on the current state and the action being dispatched.

Finally, we subscribe to the Redux Store, so our render function runs anytime the state changes, so the counter gets the current state.

8. Avoiding Array Mutations with Concat, Slice, and Spread

Watch this lesson

In this lesson, I use expect Library to make test assertions, and deep-Freeze to make sure that my code is free of mutations.

Let's say that I want to implement a count release application. I would need to write a few functions that operate on its state, and its state is an array of JavaScript numbers representing the individual counters.

The first function I want to write is called addCounter, and all it should do is to append a 0 at the end of the past array.

const addCounter = (list) => {

};

const testAddCounter = () => {
  const listBefore = [];
  const listAfter = [0];
  expect(
    addCounter(listBefore)
  ).toEqual(listAfter);
};

testAddCounter();
console.log('All tests passed');

At first, I use the array push method to add a new item at the end of the array, and it works.

const addCounter = (list) => {
  list.push(0);
  return list;
};

However, we need to learn to avoid mutations in Redux, and I'm enforcing this by calling deepFreeze on the original array.

deepFreeze(listBefore);

Now my attempt to push does not work. It cannot add a new property to a frozen object. Instead of push, I'm going to use the concat method, which does not modify the original array.

const addCounter = (list) => {
  return list.concat([0]);
};

Now the tests pass without mutations, and I can also use the new ES6 array spread operator to write the same code in a more concise way.

const addCounter = (list) => {
  return [...list, 0];
};

My next function is called removeCounter, and it accepts two arguments, an array of numbers, and the index of the number to skip from the array.

const removeCounter = (list, index) => {

};

const testRemoveCounter = () => {
  const listBefore = [0, 10, 20];
  const listAfter = [0, 20];

  expect(
    removeCounter(listBefore, 1)
  ).toEqual(listAfter);
};

If I've got three numbers and I'm passing one as the second argument, I expect to receive an array with two numbers with the second item skipped in the result array.

Usually, to delete an item from the array, I would use the splice method. However, splice is a mutating method, so you can't use it in Redux.

const removeCounter = (list, index) => {
  list.splice(index, 1);
  return list;
};

I'm going to deepFreeze the array object, and now I need to figure out a different way to remove an item from the array without mutating it.

I'm using a method called slice here, and it doesn't have anything to do with splice. It is not mutating, and it gives me a part of the array from some beginning to some end index.

const removeCounter = (list, index) => {
  return [
    ...list.slice(0, index),
    ...list.slice(index + 1)
  ];
};

What Im doing is that Im taking the parts before the index I want to skip and after the index I want to skip, and I concatenate them to get a new array.

Finally, instead of writing it as a method chain with concat calls, I can use the ES6 array spread operator to write it more concisely.

Now that we implemented adding and removing counters, let's implement increment in the counter. The incrementCounter function takes two arguments, the array and the index of the counter that should be incremented, so the return value has the same count of items, but one of them is incremented.

const incrementCounter = (list, index) => {

};

const testIncrementCounter = () => {
  const listBefore = [0, 10, 20];
  const listAfter = [0, 11, 20];

  expect(
    incrementCounter(listBefore, 1)
  ).toEqual(listAfter)
};

Directly setting the array value at index works, but this is a mutation. If we add a deepFreeze call, it's not going to work anymore, so how do we replace a single value in the array without mutating it?

const incrementCounter = (list, index) => {
  list[index]++;
  return list;
};

It turns out that the answer is really similar to how we remove an item. We want to take the slice before the index, concat it with a single item array with a new value, and then concat it with the rest of the original array.

const incrementCounter = (list, index) => {
  return [
    ...list.slice(0,index),
    list[index] + 1,
    ...list.slice(index + 1)
  ];
};

Finally, with the ES6 spread operator, we can spread over the left part of the array, specify the new item, and then spread over the right part of the original array, and this looks much nicer.

In this lesson, you learned how to use the concat method or the spread operator, and the slice method to add, remove, and change items in arrays without mutating them, and how to protect yourself with deepFreeze from mutation in your tests.

9. Avoiding Object Mutations with Object Assign and Spread

Watch this lesson

Like in previous example, I use expect and deep-freeze libraries from NPM to make my test assertions. This time, I'm testing a function called toggleTodo that takes our todo object and flips its completed field. If completed was false, it should be true in the return value. If it was true, it should be false.

const toggleTodo = (todo) => {

};

const testToggleTodo = () => {
  const todoBefore = {
    id: 0,
    text: 'Learn Redux',
    completed: false
  };
  const todoAfter = {
    id: 0,
    text: 'Learn Redux',
    completed: true
  };

  expect(
    toggleTodo(todoBefore)
  ).toEqual(todoAfter);
};

testToggleTodo();
console.log('All tests passed.');

Just like in the previous lesson, I'm going to start by writing a mutated version that passes the current test. A mutated version just flips the completed field, reassigns it on the past object.

const toggleTodo = (todo) => {
  todo.completed = !todo.completed;
  return todo;
};

While it works, we know that mutations are not allowed in Redux. So to enforce this, I'm calling deepFreeze on my todo object. I'm not allowed to change its completed field anymore.

One way out of this would be to create the new object with every field copied from the original object except the completed field, which would be flipped.

const toggleTodo = (todo) => {
  return {
    id: todo.id,
    text: todo.text,
    completed: !todo.completed
  };
};

However, if we later add new properties to the new object, we might forget to update this piece of code to include them.

This is why I suggest you to use Object.assign method, which is new to ES6. It lets you assign properties of several objects onto the target object. Note how the object assign argument order corresponds to that of the JavaScript assignment operator.

const toggleTodo = (todo) => {
  return Object.assign({}, todo, {
    completed: !todo.completed
  });
};

The left argument is the one whose properties are going to be assigned, so it's going to be mutated. This is why we're passing an empty object as the first argument, so we don't mutate any existing data. Every further argument to Object.assign will be considered one of the source objects whose properties will be copied to the target object.

It is important that if several sources specify different values for the same property, the last one wins. This is what we use to override the completed field despite what the original todo object says.

Finally, you need to remember that Object.assign is a new method in ES6, so it is not natively available in all the browsers. You should use a polyfill, either the one that ships with Babel or a standalone Object.assign polyfill, to use it without risking crashing your website.

Another option that doesn't require a polyfill is to use the new object spread operator, which is not part of ES6. However, it is proposed for ES7. It is fairly popular, and it is enabled in Babel if you use the stage two preset.

const toggleTodo = (todo) => {
  return {
    ...todo,
    completed: !todo.completed
  };
};

10. Writing a Todo List Reduce in Redux: Adding a Todo

Watch this lesson

Just like in the previous two lessons, I'm using expect library to make test assertions and deep-freeze library to prevent accidental mutations in my code. In this lesson, I will create the reducer for a todo list application whose state is described an array of todos.

Just to remind you what a reducer is, it's a pure function you write to implement the update logic of your application -- that is, how the next state is calculated given the current state and the action being dispatched.

const todos = (state = [], action) => {

};

Before writing a reducer, I want to have a way of knowing whether its code is correct, so I'm starting by writing a test for it. I'm declaring two variables, the stateBefore, which is an empty array, and the action being dispatched, which is an action describing user adding any todo with some ID and a text.

const testAddTodo = () => {
  const stateBefore = [];
  const action = {
    type: 'ADD_TODO',
    id: 0,
    text: 'Learn Redux'
  };
  const stateAfter = [
    {
      id: 0,
      text: 'Learn Redux',
      completed: false
    }
  ];
};

I am also declaring the state I expect to get after calling the reducer. Like state before, it is an array, but this time, it has a single element representing the todo that was just added. So it has the same id and the text as the action object. It also has an additional field called, completed, that I want to be initialized to be false.

const testAddTodo = () => {
  const stateBefore = [];
  const action = {
    type: 'ADD_TODO',
    id: 0,
    text: 'Learn Redux'
  };
  const stateAfter = [
    {
      id: 0,
      text: 'Learn Redux',
      completed: false
    }
  ];
};

We want to make sure that the reducer is a pure function, so I'm calling deepFreeze both on the stateBefore and the action.

deepFreeze(stateBefore);
deepFreeze(action);

Finally, I am ready to use the expect library to verify that if I call the todo reducer with the stateBefore and the action object, I'm going to get the result that is deeply equal to the stateAfter I just declared.

expect(
  todos(stateBefore, action)
).toEqual(stateAfter);

This concludes my first test. Now I can call it just like a regular JavaScript function. If it doesn't throw an the expect call, I'm going to see a message saying that the tests have passed.

Of course, it fails because the reducer is not implemented yet. It's an empty function. So it returns undefined instead of the array with a single item that I expect in the test.

To fix this, I would need my reducer to take a look at the action.type property, which is a string. When it matches the ADD_TODO string, which I specify as the action.type in my test, to satisfy the test I need to return a new array which includes all items from the original array but also a new todo item that has its id and text copied from the action object and a completed field set to false.

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ];
      default:
        return state;
  }
};

Finally, I add a default case to my switch statement because every reducer has to return the current state for any unknown action.

Now the test runs successfully. Let's recap the data flow in this example to see why.

First, I create the state array, which is an empty array, and the action object inside my test function. I'm passing them as arguments to my reducer function, called, todos.

const testAddTodo = () => {
  const stateBefore = [];
  const action = { ... };
  const stateAfter = [ ... ];
};

expect(
  todos(stateBefore, action)
  ).toEqual(stateAfter);

The todos reducer accepts the state and the action as arguments and takes a look at the action.type.

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ];
    default:
      return state;
  }
};

In this case, the action.type is a string saying, ADD_TODO, so it matches the switch case inside the reducer. The reducer returns a new array which contains the items from the old array and the new item representing the added todo.

However, the state we passed from the test was actually an empty array, so, at the end, we're going to get an array with a single item, which is the new todo.

Finally, we compare the return value to an array with a single todo item to make sure that the reducer works as intended. The equality check passes. This makes the test successful.

11. Writing a Todo List Reduce in Redux: Toggling a Todo

Watch this lesson

In this lesson, we will continue creating the reducer for todo list application. The only action that this reducer currently handles is called ADD_TODO. We also created a test that makes sure that when the reducer is called with an empty array as a state and the ADD_TODO action, it returns an array with a single to do element.

const testAddTodo = () => {
  const stateBefore = [];
  const action = {
    type: 'ADD_TODO',
    id: 0,
    text: 'Learn Redux'
  };
  const stateAfter = [
    {
      id: 0,
      text: 'Learn Redux',
      completed: false
    }
  ];
};

In this lesson, we will follow the same approach to implement another action called TOGGLE_TODO. We're going to start with a test again. This time, we're testing a different action and we have a different initial state. The state before calling the reducer now includes two different todos with id: 0 and 1. Notice how both of them have their completed fields set to false.

const testToggleTodo = () => {
  const stateBefore = [
    {
      id: 0,
      text: 'Learn Redux',
      completed: false
    },
    {
      id: 1,
      text: 'Go shopping',
      completed: false
    }
  ];
};

Next, I declare the action. The action is an object with the type property which is a TOGGLE_TODO string and the id of the todo that I want to be toggled. I declare the state that I expect to receive after calling the reducer. It's pretty much the same as before calling the reducer. However, I expect the todo with the id specified in the action or 1 in this case. The change is completed field.

const action = {
  type: 'TOGGLE_TODO',
  id: 1
};
const stateAfter = [
  {
    id: 0,
    text: 'Learn Redux',
    completed: false
  },
  {
    id: 1,
    text: 'Go shopping',
    completed: true
  }
];

The reducer must be a pure function. As a matter of precaution, I called deepFreeze on the state and the action. Finally, just like in the previous lesson, I'm asserting that the result of calling my reducer with the stateBefore and the action is going to be deeply equal to the stateAfter.

deepFreeze(stateBefore);
deepFreeze(action);

expect(
  todos(stateBefore, action)
).toEqual(stateAfter);

My test is a function, so I need to call it at the end of the file. If I run it, it fails because I have not implemented handling this action yet.

I'm adding a new switch case to my reducer. I remember that I shouldn't change the original array, so I'm using the array map method to produce a new array.

The function I pass as an argument will be called for every todo. If it's not a todo I'm looking for, I don't want to change it. I just return it as is. However, if the todo is the one we want to toggle, I'm going to return a new object that has all the properties of the original todo object thanks to the object's spread operator, but also an inverted value of the completed field.

case 'TOGGLE_TODO':
      return state.map(todo => {
        if (todo.id !== action.id) {
          return todo;
        }

        return {
          ...todo,
          completed: !todo.completed
        };

Now both of our tests run successfully. We have an implementation of the reducer that can add and toggle todos.

12. Redux Reducer Composition with Arrays

Watch this lesson

In the previous lesson we created a reducer that can handle two actions, adding a new todo, and toggling an existing todo. Right now, the code to update the todo item or to create a new one is placed right inside of the todos reducer.

This function is hard to understand because it makes us two different concerns, how the todo's array is updated, and how individual todos are updated. This is not a problem unique to Redux. Any time a function does too many things, you want to extract other functions from it, and call them so that every function only addresses a single concern.

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        id: action.id,
        text: action.text,
        completed: false
      };
  }
};

In this case, I decided that creating and updating a todo in response to an action is a separate operation, and needs to be handled by a separate function called todo.

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        todo(undefined, action)
      ];
  }
}

As a matter of convention, I decided that it should also accept two arguments, the current state and the action being dispatched, and it should return the next state.

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return { ... };
    case 'TOGGLE_TODO':
      if (todo.id !== action.id) {
        return state;
      }

      return {
        ...state,
        completed: !state.completed
      };
  }
};

But in this case, this state refers to the individual todo, and not to the list of todos. Finally, there is no magic in Redux to make it work. We extracted the todo reducer from the todos reducer, so now we need to call it for every todo, and assemble the results into an array.

switch (action.type) {
  case 'ADD_TODO':
    return { ... };
  case 'TOGGLE_TODO':
    return stat.map(t => todo(t, action));
  default:
    return state;
}

While this is not required in this particular example, I suggest that you always have the default case where you return the current state to avoid all problems in the future. The pattern described in this lesson is pervasive in Redux's development, and is called reducer composition.

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return { ... };
    case 'TOGGLE_TODO':
      if (todo.id !== action.id) {
        return state;
      }

      return {
        ...state,
        completed: !state.completed
      };
    default:
      return state;
  }
};

Different reducers specify how different parts of the state tree are updated in response to actions. Reducers are also normal JavaScript functions, so they can call other reducers to delegate and abstract a way of handling of updates of some parts of this tree they manage.

This pattern can be applied many times, and while there is still a single top level reducer managing the state of your app, you will find it convenient to express it as many reducers call on each other, each contribution to a part of the applications state tree.

13. Redux Reducer Composition with Objects

Watch this lesson

In the previous lesson, we established the pattern of reducer composition where one reducer can be called by another reducer to update items inside an array.

If we create a store with this reducer and log its state, we will find that the initial state of it is an empty array of todos. If we dispatch an ADD_TODO action, we will find that the corresponding to do has been added to the state array.

If we dispatch another ADD_TODO action, the corresponding to do will also be added at the end of the array and dispatch in a TOGGLE_TODO action with id: 0 will flag the completed field of the to do with id: 0.

Representing the whole state of the application as an array of todos works for a simple example, but what if we want to store more information? For example, we may want to let the user choose which todos are currently visible with the visibilityFilter such as show completed, SHOW_ALL, or SHOW_ACTIVE.

const visibilityFilter = (
  state = 'SHOW_ALL',
  action
) => {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter;
    default:
      return state;
  }
};

The state of the visibilityFilter is a simple string representing the current filter. It is changed by SET_VISIBILITY_FILTER action.

To store this new information, I don't need to change the existing reducers. I will use the reducer composition pattern and create a new reducer that calls the existing reducers to manage parts of its state and combines the results in a single state object.

const todoApp = (state = {}, action) => {
  return {
    todos: todos(
      state.todos,
      action
    ),
    visibilityFilter: visibilityFilter(
      state.visibilityFilter,
      action
    )
  }
}

Now that the first time it runs, it will pass undefined as the state of the child reducers because the initial state of the combined reducer is an empty object, so all its fields are undefined. This gets the child reducers to return their initial states and populates the state object for the first time.

When an action comes in, it calls the reducers with the pass of the state that they manage and the action and combines the results into the new state object.

This is another example of the reducer composition pattern, but this time we use it to combine several reducers into a single reducer that we will now use to create our store.

const store = createStore(todoApp);

The initial state of the combined reducer now contains the initial states of independent reducers. Any time an action comes in, those reducers handle the action independently.

This pattern helps scale Redux's development because different people on the team can work on different reducers handling the same actions without running into each other and causing merge conflicts.

Dispatching visibility Filter

Finally, I'm dispatching the SET_VISIBILITY_FILTER action. You can see that it doesn't affect the todos, but the visibilityFilter field has been updated.

14. Redux Reducer Composition with CombineReducers

Watch this lesson

In the previous lesson we learned how to use the reducer composition pattern to let different reducers handle different parts of the state tree, and then combine their results.

This pattern is so common that it's present in most Redux applications. This is why Redux provides a function called combineReducers that lets you avoid writing this code by hand. Instead, it generates the top level reducer for you.

const { combineReducers } = Redux;
const todoApp = combineReducers({
  todos: todos,
  visibilityFilter: visibilityFilter
});

The only argument to combine reducers is an object. This object lets me specify the mapping between the state field names, and the reducers managing them. The return value of the combineReducer is called a Reducer function, which is pretty much equivalent to the reducer function I wrote by hand previously.

The keys of the object I configure combinedReducers with correspond to the fields that the state object is going to manage. The values of the object I have asked to combineReducer, are the producers we should call to update the correspondence state fields.

const todos = (state = [], action) => {
  switch (action.type) { ... }
};

const visibilityFilter = (
  state = 'SHOW_ALL',
  action
) => {
  switch (action.type) { ... }
};

This combineReducer call says that the todo's field inside the state object managers will be updated by the todos reducer, and the visibilityFilter field inside the state object will be updated by calling the visibilityFilter reducer. The results will be assembled into a single object. In other words, it behaves pretty much exactly as the function commented down below.

//  const todoApp = (state = {}, action) => {
//    return {
//      todos: todos(
//       state.todos,
//        action
//     ),
//      visibilityFilter: visibilityFilter(
//        state.visibilityFilter,
//        action
//      )
//    };
//  };

Finally, I will establish a useful convention. I will always name my reducers after the state keys they manage. Since the key names and the value names are now the same, I can omit the values thanks to the ES6 object literal shorthand notation.

const todoApp = combineReducers({
  todos,
  visibilityFilter
});

In this lesson, you learned how to generate a simple reducer that calls many reducers to manage parts of its state by using the combineReducers utility function.

15. Implement Redux CombineReducers from Scratch

Watch this lesson

In the previous lesson, we learned to use the combineReducer function, which comes with Redux and generates one reducer from several other reducers, delegating to them paths of the state tree.

const { combineReducer } = Redux;
const todoApp = combineReducer({
  todos,
  visibilityFilter
});

To gain a deeper understanding of how exactly combinedReducers works, we will implement it from scratch in this lesson.

CombineReducers is a function, so I'm writing a function declaration. Its only argument is the mapping between the state keys and the reducers, so I'm just going to call it reducers.

const combineReducer = (reducers) => {

};

The return value is supposed to be a reducer itself, so this is a function that returns another function. The signature of the return function is a reducer signature. It has the state and the action.

const combineReducer = (reducers) => {
  return (state = {}, action) => {

  };
};

Now, I'm calling the Object.keys method, which gives me all the keys of the reducer's object. In our example, this is todos and the visibilityFilter.

Next, I'm calling the reduce method on the keys, because I want to produce a single value, such as the nextState, by accumulating over every reducer key and calling the corresponding reducer. Each reducer passed through the combineReducers function is only responsible for updating a part of the state. This is why I'm saying that the nextState by the given key can be calculated by calling the corresponding reducer by the given key with the current state by the given key and the action.

const combineReducer = (reducers) => {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce(
      (nextState, key) => {
        nextState[key] = reducers[key](
          state[key],
          action
        );
        return nextState;
      },
      {}
    );
  };
};

The array reduce wants me to return the next accumulated value from the call back, so I'm returning the nextState. I'm also specifying an empty object as the initial next state, before all the keys are processed.

There we have it. This is a working reimplementation of combinedReducers utility from Redux.

Let's briefly recap how it works. I'm calling combinedReducers with an object whose values are the reducer functions and keys are the state field they manage.

const todoApp = combineReducer({
  todos,
  visibilityFilter
});

Inside the generated reducer, I'm retrieving all the keys of the reducers I passed to combineReducers, which is an array of strings, todos and visibilityFilter.

const combineReducer = (reducers) => {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce(
      (nextState, key) => {
        nextState[key] = reducers[key](
          state[key],
          action
        );
        return nextState;
      },
      {}
    );
  };
};

I'm starting with an empty object for my next state and I'm using the reduce operation of these keys to fill it gradually.

Notice that I'm mutating the next state object on every iteration. This is not a problem, because it is the object I created inside the reducer. It is not something passed from outside, so reducer stays a pure function.

To calculate the next state for a given key, it calls the corresponding reducer function, such as todos or visibilityFilter.

(nextState, key) => {
  nextState[key] = reducers[key](
    state[key],
    action
  );
  return nextState;
}

The generated reducer will pass through the child reducer only if part of its state by the key. If its state is a single object, it's only going to pass the relevant part, such as todos or visibility filter, depending on the current key, and save the result in the next state by the same key.

Finally, we use the array reduce operation with the empty object as the initial next state, that is being filled on every iteration until it is the return value of the whole reduce operation.

In this lesson, you learned how to implement the combinedReducers utility that comes with Redux from scratch.

It is not essential to use in Redux, so it is fine if you don't fully understand how it works yet. However, it is a good idea to practice functional programming and understand functions can take other functions as arguments and return other functions, because knowing this will help you get more productive in Redux in the long term.

16. Redux Example: Adding a Todo to a List

Watch this lesson

In the previous lessons, we learned how to split the root reducer into many smaller reducers that manage parts of the state tree.

We have a ready todoApp reducer that handles all the actions of our simple todo application. Now it's trying to implement the View layer. I'm going to use React in this example.

I'm adding react and react-dom packages from the Facebook CDN. I'm also adding a div with the id='root', which is where I'm going to render my react application.

<body>
  <div id='root'></div>
</body>

Similar to the react counter-example from the eighth lesson, I declare a render function that is going to update dom in response to the current application state. I'm going to subscribe to these core changes and call render whenever the store changes and wants to render the initial state.

const render = () => {

};

store.subscribe(render);
render();

The implementation of the render method is going to use react, so it's called ReactDOM.render for some todoApp component I haven't written yet. It renders it into the div I created inside the HTML. It's div with the id called root.

const render = () => {
  ReactDOM.render(
    <todoApp />,
    document.getElementById('root')
  );
};

React provides a base class for all components. I'm grabbing from the react object called reactComponent. I'm declaring my own todoApp component that extends the react-based Component. This component is only going to have a render function and is going to return a div. Inside the div, I'm going to place a button saying add todo them.

const { Component } = React;

class todoApp extends Component {
  render() {
    return (
      <div>
        <button onClick={() => { }}>
          Add todo
        </button>
      </div>
    );
  }
}

I don't want to add an input field yet to keep the example simple at first. I'm dispatching the ADD_TODO action, and I'm going to put a Test as my checks for the action. It's going to keep adding to this with the products test.

<button onClick={() => {
  store.dispatch({
    type: 'ADD_TODO',
    text: 'Test',
    id: nextTodoId++
  });
}}>

The ID, I need to specify a sequential ID. This is why I'm declaring an global variable called NextToID, and I'm going to keep in command in it. Every time, it's going to emit a new id.

let nexttodoId = 0;

I also want to display a list of the todo list. Assuming that I have the todos inject as todos prop, I'll call map and for every todo item, I'm going to show a list item show in the text of that particular todo.

<ul>
  {this.props.todos.map(todo =>
    <li key={todo.id}>
      {todo.text}
    </li>
   )}
</ul>

Finally, because I need to the todos as a prop, I'm going to pass it to the todoApp by reading the currents stores state and written its todo field.

  <todoApp todos={store.getState().todos} />

Adding todos

You can see that there is a button add todo and anytime I press it, I see a new todo with a test text. I'm going to add an input inside my render function, and I'm using the react callback ref API where ref is a function, it gets the node corresponding to the ref, and I'm saving that node with some name. In this case, this.input.

<input ref={node => {
  this.input = node;
}} />

I'm able to read the value of the input inside my event handler. I'm reading this this.input.value. I'm also able to reserve the value after dispatching the action so that the field is cleared.

<button onClick={() => {
  store.dispatch({
    type: 'ADD_TODO',
    text: this.input.value,
    id: nextTodoId++
  });
  this.input.value = '';
}}>

If I try write something to build and press Add Todo, the ADD_TODO action is dispatched and the field is cleared.

Adding todos with this.input

Let's take a moment to recap how this application works. It starts with a todoApp react component. This component is not aware of how exactly todos are being added. However, it can express its desire to mutate the state by dispatching an action with the type ADD_TODO.

<button onClick={ () => {
  store.dispatch({
    type: 'ADD_TODO',
    text: this.input.value,
    id: nextTodoId++
  });
  this.input.value = '';
}}>

For the text field, it uses the current input value and it passes an incrementing id as the id of todo. Every todo needs its own id, and in this approach, we're just going to increment the counter, so it always gives us the next integer as id.

It is common for react components to dispatch actions in Redux apps. However, it is equally important to be able to render the current state. My todoApp component assumes that it's going to receive todos as a prop, and it maps over the todo list to display a list of them using the todo.id as a key.

<ul>
  {this.props.todos.map(todo =>
    <li key={todo.id}>
      {todo.text}
    </li>
  )}
</ul>

This component is being rendered in the render function that runs any time the store state changes and initially. The render function reads the current state of this store and passes the todos array that it gets from the current state of this store to do to the app component as a prop.

const render = () => {
  ReactDOM.render(
    <todoApp
      todos={store.getState().todos}
    />,
    document.getElementById('root')
  );
};

The render function is called on every store change so the todos prop is always up to date. This was the rendering part of the redux flow. Let's recap how mutations work in Redux.

Any state change is caused by a store.dispatch call somewhere in the component. When an action is dispatched, this store calls the reducer it was created with, with the current state and the action being dispatched.

In our case, this is the todoApp reducer, which we obtained by combining visibilityFilter and the todos reducer.

It matches the action type and the switch statement. If the action type is ADD_TODO and indeed, it is equal to ADD_TODO string. In this case, it will call the child todo reducer, passing it undefined, because this is no state for a new todo that it can pass in the action.

case 'ADD_TODO':
  return [
    ...state,
    todo(undefined, action)
  ];

We have a similar switch statement inside the todo reducer and the action type is ADD_TODO returns the initial state of the todo. With the id and text from the action and the completed field set to false.

case 'ADD_TODO':
  return {
    id: action.id,
    text: action.text,
    completed: false
  };

The todos reducer that called it was returned a new array with all existent items and the new item added at the very end. It adds a need to do to the current state.

Finally, the combined producer called todoApp will use this new array as the new value for the todos field in the global state object. It's going to return a new state object where the todos field corresponds to the array with the newly-added todo item.

const todoApp = combineReducers({
  todos,
  visibilityFilter
});

The todoApp reducer is the root reducer in this application. It is the one the store was created with. Its next state is a next state of the Redux store, and all the listeners are notified.

The render function is subscribed to the store changes so it is called again, and it gets the fresh state by call and getState and it passes the fresh todos to the component, re-rendering it with the new data.

const render = () => {
  ReactDOM.render(
    <TodoApp
      todos={store.getState().todos}
    />,
    document.getElementById('root')
  );
};

store.subscribe(render);
render();

17. Redux Example: Toggling a Todo in the List

Watch this lesson

In the last lesson, we implemented a simple UI for the todo list application that is able to add new todos and view the existing todos in the list.

To add the todos, we dispatched the ADD_TODO action. In this lesson, we're going to dispatch the TOGGLE_TODO action to toggle the completed state of the todos by clicking on them.

I'm scrolling down to my React component. I've got a list item here corresponding to the todo, so I'm adding the onClick handler. When the user clicks on the list item, I want to dispatch an action to my store with a type TOGGLE_TODO and the id of the todo being toggled, which I get from the todo object.

The event handler knows which todo it corresponds to, so it is able to pass its id in the action.

<ul>
  {this.props.todos.map(todo =>
    <li key={todo.id}
        onClick={ () => {
          store.dispatch({
            type: 'TOGGLE_TODO',
            id: todo.id
          });         
        }}>
      {todo.text}
    </li>
  )}
</ul>

In the user interface, I want the completed todos to appear crossed out, so I'm adding this style attribute to the list item. I'm going to use the textDecoration property, which is going to be a line-through when todo.completed is true, and none when todo.completed is false, so I get a normal looking todo.

style={{
  textDecoration:
    todo.completed ?
      'line-through' : 'none'
}}>

Now, if I add a couple of todos, I can click on them and they're going to appear toggled, and I can toggle them back. Isn't that satisfying?

Toggling Todos

Let's recap how toggling the todo actually works.

It starts with me dispatching the TOGGLE_TODO action inside my click handler, with a type TOGGLE_TODO and the id, which is the id of the todo being rendered.

onClick={() => {
  store.dispatch({
    type: 'TOGGLE_TODO',
    id: todo.id
  });         
}}

I get the todo object as an argument to the array map call back inside my render method where I render all the todos.

When an action is dispatched, the store will call the root reducer, which will call the todos reducer with the array of todos and the action. In this case, the action type is TOGGLE_TODO, so the todos reducer delegates handling of every todo to the todo reducer with a map function to call it for every todo item. The todos reducer receives the todo as state, and the action.

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [ ... ];
    case 'TOGGLE_TODO':
      return state.map(t =>
        todo(t, action)
      );
    default:
      return state;
  }
};

Again, we switch on the action type, and it matches TOGGLE_TODO string. Now, for every todo whose id does not match the id specified in the action, we just return the previous state, that is the todo object, as it was.

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO': { ... }
    case 'TOGGLE_TODO': 
      if (state.id !== action.id) {
        return state;
      }
      return {
        ...state,
        completed: !state.completed
      };
    default:
      return state;
  }
};

However, if the id of the todo matches the one specified in the action, we're going to return any object with all the properties of the original todo, but with the completed field equal to the opposite value of what it was.

The updated todo item will be included in the todos field under the new application state. Because we subscribe, the render function is going to get the next state of the application in store, getState(), and pass the new version of the todos to the TodoApp component, which is going to render the updated todos.

const render = () => {
  ReactDOM.render(
    <TodoApp
      todos={store.getState().todos}
    />,
    document.getElementById('root')
  );
};

store.subscribe(render);
render();

Finally, this child of the list item, depends on the todo.completed field, which we just updated, which is why it re-renders in a cross-child state.

18. Redux Example: Filtering Todos in a List

Watch this lesson

In the previous two lessons, we were working on creating the user interface for the todo list application that displays the todos, lets us add new todos, and toggle them on click. We implemented that by dispatching ADD_TODO and TOGGLE_TODO actions that we already know how to handle in our reducers.

In this lesson, we're going to dispatch SET_VISIBILITY_FILTER reaction and use the visibilityFilter field to only show the todos the user wants to see -- either the completed todos, active todos, or all todos in the current state.

I'm starting by creating a new functional component called, FilterLink that the user needs to click to switch the current visible todos. The FilterLink accepts the filter prop, which is just a string, and the children, which is the contents of the link. It's going to be a simple <a> tag that doesn't really link anywhere. It's going to prevent the navigation when clicked.

const FilterLink = ({
  filter,
  children
}) => {
  return (
    <a href='#'
       onClick={e => {
         e.preventDefault();
         store.dispatch({
          type: 'SET_VISIBILITY_FILTER',
          filter
         })
       }}
    >
      {children}
    </a>
  );
};

It's going to dispatch an action, the type, SET_VISIBILITY_FILTER, and pass in the filter prop so that the reducer knows which filter is being clicked. I will pass the children down to the <a> tag, so the consumer can specify the text of the link. Now I can use it in my TodoApp component.

Just below the todo list, I am adding a paragraph where I'm going to offer the user the choice as to which todos should be currently visible by using the filter link component I just created.

<ul>
  {this.props.todos.map(todo =>
  <li key={todo.id}
      onClick={() => { store.dispatch({ ... });}}
      style={{ ... }}>
      {todo.text}
  </li>
  )}
</ul>
  <p>
    Show:
  </p>

The filter prop is one of the three possible values, such as SHOW_ALL, which corresponds to showing every todo in the state, SHOW_ACTIVE, which means just show the todos that are not completed yet, and SHOW_COMPLETED, which means show the completed todos. I'm copy-pasting the filter link, and I'm changing the labels and the filters corresponding to it.

<p>
  Show:
  {' '}
  <FilterLink
    filter='SHOW_ALL'
  >
    ALL
  </FilterLink>
  {' '}
  <FilterLink
    filter='SHOW_ACTIVE'
  >
    Active
  </FilterLink>
  {' '}
  <FilterLink
    filter='SHOW_COMPLETED'
  >
    Completed
  </FilterLink>
</p>

Running this code will give me three different things under the list of todos. Clicking on them will change the state visibilityFilter field. However, it doesn't have any effect yet because we don't interpret the value of the visibilityFilter.

I am creating a new function that is going to help me filter the todos according to the filter value. It's called, getVisibleTodos. It accepts two arguments, the todos and the filter. It switches on the current filter value.

const getVisibleTodos = (
  todos,
  filter
) => {
  switch (filter) {
    case 'SHOW_ALL':
      return todos;
    case 'SHOW_COMPLETED':
      return todos.filter(
        t => t.completed
      );
    case 'SHOW_ACTIVE':
      return todos.filter(
        t => !t.completed
      );
  }
}

If the filter is SHOW_ALL, it's going to return all of the todos. But if the filter is SHOW_COMPLETED, it's going to call todos.filter, that is array filter method, to only return those todos that have completed set to true. SHOW_ACTIVE is going to the opposite of that. It's going to return only those todos where a completed field is false.

Now I need to call this function to filter the todos before rendering them. In the render function of the TodoApp component, I get the visible todos by calling getVisibleTodos with the todos and the visibilityFilter values from my props.

render() {
  const visibleTodos = getVisibleTodos(
    this.props.todos,
    this.props.visibilityFilter
  );
  return ( ... );
}

I'm going to use the visibleTodos instead of this.props.todos when I enumerate them for rendering.

<ul>
  {visibilityTodos.map(todo =>
  <li key={todo.id}
      onClick={() => { store.dispatch({ ... });}}
      style={{ ... }}>
      {todo.text}
  </li>
  )}
</ul>

Finally, I now use the visibilityFilter inside my TodoApp component, so I need to pass it as a prop.

I could do this explicitly, but actually it's easier for me just to spread over all the state fields. So every state field inside the state object is passed as a prop to the TodoApp component. This way, it receives the visibilityFilter. If I add some todo items and then click on them, so I change their completed fields, and then click on the visibilityFilter links, the currently visible todos are rendered according to the chosen visibilityFilter.

<TodoApp
  {...store.getState()}
/>

Filters Applied

The links look all the same right now, but we want to highlight the chosen one. To implement this, we're going to need the visibilityFilter prop which says which is the current one.

I'm changing the beginning of the render method to destructure the todos and the visibilityFilter from the props, so I can access them directly now without typing this.props every time.

const {
  todos,
  visibilityFilter
} = this.props;
const visibleTodos = getVisibleTodos(
  todos,
  visibilityFilter
);

I'm going to pass the visibilityFilter to every <FilterLink>, so it can know which filter is the current one and apply different styling if the currentFilter matches the filter links' own filter.

<FilterLink
  filter='SHOW_ALL'
  currentFilter={visibilityFilter}
>

After passing the currentFilter prop to every filter link, I go back to the FilterLink declaration. I'm adding currentFilter as a prop to it, and I'm adding a condition that says that when the filter is the currentFilter, that is, when the link is active, I want to return a <span> instead of a link because I don't want it to be clickable. I want it to be static text.

if (filter === currentFilter) {
  return <span>{children}</span>;
}

This completes the user interface of our todo list example. It lets us add items. It lets us view items, toggle them as completed. When we switch the visibilityFilter, it displays only relevant todos, and it also updates the link appearance, so we see which link is active.

Updated Link Appearance

Let's recap how a change in the visibilityFilter works. It starts with a dispatch code with an action of the type SET_VISIBILITY_FILTER. It passes filter, which is a prop, to the link component, so every one of those three links is going to have a different filter prop it passes in the action.

<a href='#'
  onClick{e => {
    e.preventDefault();
    store.dispatch({
      type: 'SET_VISIBILITY_FILTER',
      filter
    });
  }}
>

The store dispatch function will call our root reducer with the state and the action which in turn will call the visibilityFilter reducer with the part of the state and the action.

Note that when the action.type is set visibilityFilter, it doesn't care for the previous state, it just returns the action.filter as the next value, the next state, of the visibilityFilter reducer.

const visibilityFilter = (
  state = 'SHOW_ALL',
  action
) => {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter;
    default:
      return state;
  }
};

The root reducer will use this new field as part of its new state object.

Because the render function is subscribed to the stored changes, it's going to get this new state object and pass all its keys as props to the TodoApp component.

const render = () => {
  ReactDOM.render(
    <TodoApp
      {...store.getState()}
    />,
    document.getElementById('root')
  );
}; 

The TodoApp component will receive the todos and the updated visibilityFilter as its props.

Both these props are passed through the getVisibleTodos function, which calculates the currently visible todos according to a list of all todos and the visibilityFilter.

const {
  todos,
  visibilityFilter
} = this.props;
const visibleTodos = getVisibleTodos(
  todos,
  visibilityFilter
);

The filter is just a string saying SHOW_ALL, completed, or active. The return value is a new array of todos that in some cases, filters them and, in some cases, returns as is. The show completed and show active are only different in their predicates.

case 'SHOW_ALL':
  return todos;
case 'SHOW_COMPLETED':
  return todos.filter(
    t => t.completed
  );
case 'SHOW_ACTIVE':
  return todos.filter(
    t => !t.completed
  );

The return value is the array of visible todos. It is used in the render function to actually enumerate every todo and render it.

The visibilityFilter field is also used by the <FilterLink> as the currentFilter because the <FilterLink> wants to know whether its filter is the current one in order to render a span instead of a link. This is how clicking a link makes it appear selected and changes the currently displayed items in the list.

<p>
  Show:
  {' '}
  <FilterLink
    filter='SHOW_ALL'
    currentFilter={visibilityFilter}
  >
    All
  </FilterLink>

19. Extracting a Redux Presentational Component for the Todo List

Watch this lesson

In the last few lessons, we created user interface for a simple React and Redux todo list where I can add items, toggle them as completed, and change the currently visible todos.

We do that by having a single TodoApp component that has the input, the button for adding todos, the list of currently visible todos with click handler. It has these three links that let us change the currently visible todos.

The single component approach worked so far. However, we really want to have many components that can be used, tested, and changed by different people separately. So we're going to refactor our application in this lesson.

The first component I want to extract from the TodoApp component is the Todo component that renders a single list item. I am declaring the Todo component as a function which React 14 allows me to do. I'm not sure which props it's going to have, so I'll leave them blank for now. I will just paste the list item I copied before.

const Todo = ({

}) => (
  key={todo.id}
  <li
    onClick={() => {
      store.dispatch({
        type: 'TOGGLE_TODO',
        id: todo.id
      });
    }}
    style={{
      textDecoration:
        completed ?
          'line-through' :
          'none'
    }}
  >
    {todo.text}
  </li>
);

The first thing I'm doing is removing the special key property because it's only needed when I enumerate an array. I'll use it later when enumerating many todos.

One of my goals with this refactoring is to make every component as flexible as it is reasonable. Right now, I have hardcoded that clicking a todo always causes the TOGGLE_TODO action. This is perfectly fine to do in your app.

However, I prefer to have a bunch of components that don't specify any behaviors, and that are only concerned with how things look or how they render. I call such components the presentational components.

I would like to give todo a presentational component, so I removed the onClick handler. I promote it to be a prop so that anyone who uses todo component can specify what happens on the click. You don't have to do this in your Redux apps, but I find it to be a very convenient pattern.

const Todo = ({
  onClick,
  completed,
  text
}) => (
<li
  onClick={onClick}
  style={{
    textDecoration:
      completed ?
        'line-through' :
        'none'
  }}
>
  {todo.text}
</li>
);

Finally, while it doesn't have a lot of difference, I prefer to keep it explicit what is the data that the component needs to render. Instead of passing a todo object, I pass completed and text fields as separate props.

const Todo = ({
  onClick,
  completed,
  text
}) => (
  <li
    onClick={onClick}
    style={{...}}
  >
    {text}
  </li>
);

Note how the todo component is now a purely presentational component and doesn't specify any behavior. But it knows how to render AddTodo.

The next component I create is called TodoList. It's also a presentational component. It's only concerned with how things look.

const TodoList = ({
  todos
}) => ();

It accepts an array of todos. It's going to render an unordered list of them by calling the todos.map function and rendering at todo component for every todo. It tells React to use todo.id as the unique key for the elements. It spreads over the todo object properties so the text and completed end up as props on the todo component.

const TodoList = ({
  todos
}) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
       />
    )}
   </ul>
);

I need to specify what happens when a todo is clicked. I could have dispatched an action here. Again, that would be fine, but I want it to be a presentational component, so I'm going to call another function, called onTodoClick(), and pass todo.id, and let it decide what should happen. onTodoClick is another prop for the TodoList.

const TodoList = ({
  todos,
  onTodoClick
}) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick{() => onTodoClick(todo.id)}
       />
    )}
   </ul>
);

Both Todo and TodoList are presentational components, so we need something I call, container components to actually pass the data from this store and to specify the behavior. In this case, the top level TodoApp component acts as a container component. We will see more examples of container components in the future lessons.

In this case, it just renders the TodoList with visibleTodos as the todos, and with a callback that says that when onTodoClick is called with a todo id, we should dispatch an action on the store with the type TOGGLE_TODO and the id of the todo.

<TodoList
  todos={visibleTodos}
  onTodoClick={id =>
    store.dispatch ({
      type: 'TOGGLE_TODO',
      id
    })
  } />

Let's recap again how this works. The TodoApp component renders a TodoList, and it passes a function to it that can dispatch an action. The TodoList component renders the Todo component and passes on click prop which calls onTodoClick.

const TodoList = ({
  todos,
  onTodoClick
}) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick{() => onTodoClick(todo.id)}
       />
    )}
   </ul>
);

The Todo component just uses the onClick prop it receives and binds it to the list item onClick. This way, when it's called, the onTodoClick is called, and this dispatches the action and updates the visibleTodos because the action updates the store.

const Todo = ({
  onClick,
  completed,
  text
}) => (
<li
  onClick={onClick}
  style={{
    textDecoration:
      completed ?
        'line-through' :
        'none'
  }}
>
  {todo.text}
</li>
);

22. Extracting a Redux Container Component for VisibleTodoList and AddTodo

Watch this lesson

In the previous lesson, I separated the Link presentational components from the FilterLink container components that is subscribed to the Redux store and that provides the data and the behavior for the Link component it renders.

While it makes the data flow a little bit less explicit, it makes it easy to use FilterLink in any component without worrying about passing additional data to the FilterLink or to the component that contains it. In this lesson we'll continue extracting the container components from the top level container component. The first candidate is the TodoList component.

I actually want to keep the TodoList presentational component. However, I want to encapsulate within the currently visible todos this into a separate container components that connects the TodoList to the Redux store. I'm going to call this component the VisibleTodoList.

class VisibleTodoList extends Component {

}

Just like when declaring the FilterLink component in the previous lesson, I calculate the data from the current component by using the current state which is the state from the Redux store. I'm using the getVisibleTodos function to calculate the currently visible todos based on all the todos from the Redux store and the current visibilityFilter from the Redux store state. I'm specifying the behavior as well. I'm saying that when the todo is clicked, we should dispatch an action with the type TOGGLE_TODO and the id of the todo being clicked.

class VisibleTodoList extends Component {
  render() {
    const props = this.props;
    const state = store.getState();

    return (
      <TodoList
        todos={
          getVisibleTodos(
            state.todos,
            state.visibilityFilter
          )
        }
        onTodoClick={id =>
          store.dipatch({
            type: 'TOGGLE_TODO',
            id
          })
        }
      />
    );
  }
}

All container components are similar. Their job is to connect a presentational components to the Redux store and specify the data and the behavior that it needs. I'm scrolling up to the FilterLink container components I wrote in the previous lesson to copy-paste this store subscription logic.

componentDidMount() {
  this.unsubscribe = store.subscribe(() =>
    this.forceUpdate()
  );
}

componentWillUnmount() {
this.unsubscribe();
}

render() { ... }

Just like the FilterLink, the VisibleTodoList is going to subscribe to this store and force an update any time this store state changes because it uses this state in its render method. Now that the VisibleTodoList is connected to the Redux store, we can use it instead of the TodoList. We no longer have to pass all the props from the top.

const TodoApp = ({
  todos,
  visibilityFilter
}) => (
  <div>
    <AddTodo ... />
    <VisibleTodoList />
    <Footer />
  </div>
);

Finally, in the previous lesson, I made AppTodo a presentational components, but I'm going to backtrack on this now. I will copy-paste the dispatch call back in line into the onClick handler inside the component because there isn't really a lot of presentation or behavior here.

It's easier to keep them together until we figure out how to split the presentation. For example, if in the future, we're going to have something like a form component, we may split it, but for now we'll keep them together.

const AddTodo = () => {
  let input;

  return (
    <div>
      <input ref={node => {
        input = node;
      }} />
      <button onClick={() => {
        store.dispatch({
          type: 'ADD_TODO',
          id: nextTodoId++,
          text: input.value
        })
        input.value = '';
      }}>
        Add Todo
      </button>
    </div>
  );
};

I'm scrolling down to my TodoApp component. I'm removing the onAddClick prop. I just noticed that none of the containers actually need any props from this state. I can remove the props of the TodoApp component. I can remove the render function that renders the TodoApp component with the current state of this store because I can just call it once, remove all the props that are related to this state and just render it as is because the container components that I render are going to subscribe to this store themselves and are going to update themselves when this store state changes.

const TodoApp = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
);

ReactDOM.render(
  <TodoApp />,
  document.getElementById('root')
);

Let's recap the data flow after separating the presentational and the container components. There is just one reactDOM.render call at the very end. We don't render again when this store state changes because the container components take care of that.

const TodoApp = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
);

ReactDOM.render(
  <TodoApp />,
  document.getElementById('root')
);

The first component I'm looking at is called AddTodo. Frankly, I can't classify it either as a presentational components or as a container components because it doesn't fit either category. The input and the button are the presentational part, but dispatching an action onClick is the behavior which is usually specified by the container.

const AddTodo = () => {
  let input;

  return (
    <div>
      <input ref={node => {
        input = node;
      }} />
      <button onClick={() => {
        store.dispatch({
          type: 'ADD_TODO',
          id: nextTodoId++,
          text: input.value
        })
        input.value = '';
      }}>
        Add Todo
      </button>
    </div>
  );
};

However, in this case, I'd rather keep them together because there isn't any state, the UI is very simple. It's hard to imagine any other behavior other than dispatching the ADD_TODO action.

The second component are rendering inside the at TodoApp is called the VisibleTodoList . This time, it is a proper container components that subscribes to this store and re-renders the TodoList any time this store state changes. It calculates the visible todos from the current Redux store state, the todos and the visibilityFilter fields. It passes them as the todos. When the todos are clicked, it's going to dispatch an action with the type TOGGLE_TODO and the id of the respective todo.

class VisibleTodoList extends Component {
  componentDidMount() {
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }
  
  componentWillUnmount() {
    this.unsubscribe();
  }
  
  render() {
    const props = this.props;
    const state = store.getState();
    
    return (
      <TodoList
        todos={
          getVisibleTodos(
            state.todos,
            state.visibilityFilter
          )
        }
        onTodoClick={id =>
          store.dispatch({
            type: 'TOGGLE_TODO',
            id
          })            
        }
      />
    );
  }
}

The actual rendering here is performed by the TodoList component that just renders the todos passed through it as prop and binds their clicks through the on onTodoClick prop.

Finally, the last component TodoApp renders is the Footer. The Footer is just a presentational component rendering three different FilterLink.

const Footer = () => (
  <p>
    Show:
    {' '}
    <FilterLink filter='SHOW_ALL'>
      All
    </FilterLink>

    ...

  </p>
);

The FilterLink is a container component. It subscribes to this store and it renders the presentational component called, Link, calculating whether it should be active based on its props and the current Redux store state and specifies the behavior what happens when it's clicked.

class FilterLink extends Component {
  componentDidMount() {
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }
  
  componentWillUnmount() {
    this.unsubscribe();
  }
  
  render() {
    const props = this.props;
    const state = store.getState();
    
    return (
      <Link
        active={
          props.filter ===
          state.visibilityFilter
        }
        onClick={() =>
          store.dispatch({
            type: 'SET_VISIBILITY_FILTER',
            filter: props.filter
          })
        }
      >
        {props.children}
      </Link>
    );
  }
}

Finally, the Link component is just a presentational component that render <a> tag. Separating the container and the presentational component is often a good idea, but you shouldn't take it as a dogma. Only do this when it truly reduces the complexity of your code base.

const Link = ({
  active,
  children,
  onClick
}) => {
  if (active) {
    return <span>{children}</span>;
  }

  return (
    <a href='#'
       onClick={e => {
         e.preventDefault();
         onClick();
       }}
    >
      {children}
    </a>
  );
};

In general, I suggest first trying to extract the presentational component. If there is too much boilerplate passing the props through them, then you can create the containers around them that load the data and specify the behavior.

23. Passing the Redux Store Down Explicitly via Props

Watch this lesson

In the previous lessons, we used this store top-level variable to refer to the Redux store. The components that access this store, such as the container components, read this state from it, subscribe to this store, and dispatch actions on this store using this store top-level variable.

This approach works fine for JS bin example where everything is in a single file. However, it doesn't scale to real applications for several reasons.

First of all, it makes your container components harder to test because they reference a specific store, but you might want to supply a different mock store in the test. Secondly, it makes it very hard to implement universal replications that are rendered on the server, because on the server, you want to supply a different store instance for every request because different requests have different data.

I'm going to start by moving this store creation code to the bottom of the file where I render my React components. I'm going to change it slightly. Instead of creating this store top-level variable, I will pass this store I create as a prop to the top-level component, so it is completely injectable into it.

ReactDOM.render(
  <TodoApp store={createStore(todoApp)} />,
  document.getElementById('root')
);

Every container component needs a reference to this store so unfortunately, we have to pass it down to every component as a prop. It's less effort than passing different data through every component, but it's still inconvenient. So, don't worry, we'll find a better solution later, but for now, we need to see the problem.

const TodoApp = ({ store }) => (
  <div>
    <AddTodo store={store} />
    <VisibleTodoList store={store} />
    <Footer store={store} />
  </div>
);

The problem is that the container components need to have this store instance to get this state from a dispatch actions and subscribe to the changes. This time, I'm changing the container component to take this store from the props using the ES6 destruction syntax, which just means "store equals props does store."

I'm doing the same here. I'm just taking this store from the props so I can call dispatch on it.

class VisibleTodoList extends Component {
  componentDidMount() {
    const { store } = this.props;
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }
  componentWillUnmount() { ... }
  render() {
    const props = this.props;
    const { store } = props;
    const state = store.getState();

    return (
      <TodoList ... />
    );
  }
}

I need to make similar changes to other container components. In this case, I have this AddTodo component, which is not exactly a container component, but it still needs its store to dispatch the ADD_TODO action, so I added it as a prop. I'm also going to add this store to the Footer component because, unfortunately, FilterLink needs it.

const Footer = ({ store }) => (
  <p>
    Show:
    {' '}
    <FilterLink
      filter='SHOW_ALL'
      store={store}
    >
      All
    </FilterLink>
    
    ... 

  </p>
);

The Footer component renders FilterLink. This is not convenient, but as I said, we'll figure out a way to avoid this later. For now, we need to pass this store down so that every container component, such as FilterLink, can use it to subscribe to the changes, to read this state and to dispatch actions without relying on a top-level variable being available.

class FilterLink extends Component {
  componentDidMount() {
    const { store } = this.props;
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render() {
    const props = this.props;
    const { store } = props;
    const state = store.getState();

    return ( ... );
  }
}

I'm changing the render method to read this store from the props. Now, all containers read this store instance from the props, and don't rely on a top-level variable that I removed.

render() {
    const props = this.props;
    const { store } = props;
    const state = store.getState();
}

Note that this change did not change the behavior or the data flow of this application. The container components subscribe to this store, just like before, and update their state in response to its changes.

However, what changed is how they access this store. Previously, they would access a top-level variable, but this approach does not scale to real-world applications. This is why, right now, I'm passing down this store as a prop, so the container components can subscribe to it.

In the future lessons, we will see how to pass this store down to the container components implicitly without introducing the top-level variable.

24. Passing the Redux Store Implicitly via Context

Watch this lesson

In the previous lesson, we got rid of the top level store variable and instead starting passing this store as a prop to the TodoApp component. So every component below receives this store as a prop. We even have to do this for presentational components because sometimes they contain container components that need this store to subscribe to the changes.

We have to write a lot of boiler plate code to pass this store down as a prop. But there is another way, using the advanced React feature called context.

I'm creating a new component called Provider. From its render method, it just returns whatever its child is. We can wrap any component in a Provider, and it's going to render that component.

class Provider extends Component {
  render() {
    return this.props.children;
  }
}

I'm changing the render call to render a TodoApp inside the Provider. I'm moving this store prop from the TodoApp to the Provider component. The Provider component will use the React advanced context feature to make this store available to any component inside it, including grandchildren.

ReactDOM.render(
  <Provider store={createStore(todoApp)}>
    <TodoApp />
  </Provider>,
  document.getElementById('root')
);

To do this, it has to define a special method getChildContext that will be called by React by using this.props.store which corresponds to this store that is passed to the Provider as a prop just once.

class Provider extends Component {
  getChildContext() {
    return {
      store: this.props.store
    };
  }

  render() {
    return this.props.children;
  }
}

This store will be part of the context that the Provider specifies for any of its children and grandchildren. The TodoApp is going to receive this context, and any component inside TodoApp is also going to receive this context object with this store inside it.

However, there is an important condition for the context to work. This condition is that you have to specify childContextTypes on the component that defines getChildContext. These are just React.PropTypes definition, but unlike prop types, the child context types are essential for the context to be turned on. If you don't specify them, no child components will receive this context.

class Provider extends Component {
  getChildContext() { ... }

  Provider.childContextTypes = {
    store: React.PropTypes.object
  };

  render() { ... }
}

The container components currently access tool by props, but we're going to change this to read this store from React context. To do that, we just wrap it to this.context. Similarly, in the render method, I'm also going to read this store from the context instead of the props.

Finally, the context is opt-in for the receiving components too, so you have to specify a special field called contextTypes, which are similar to childContextType. But, in this case, we are specifying which context we want to receive and not pass down. If you forget to declare the contextTypes, the component will not receive the relevant context, so it is essential to remember to declare them.

VisibleTodoList.contextTypes = {
  store: React.PropTypes.object
};

What about the functional components that don't have this? It turns out that they also receive the context but as a second argument after the props. I'm destructuring the second argument and getting this store from there. The second argument is the context.

const AddTodo = (props, { store }) => { ... }

Just like with the class components, I still have to add a property called, contextTypes that specifies which context I want to receive. In this case, I want to receive the store from the Provider. If I forget to declare the contextTypes, my functional component will not receive the relevant context as a second argument. It's important to remember to declare them any time you use the context.

AddTodo.contextTypes = {
  store: React.PropTypes.object
};

Finally, I'm replacing the props with the context when getting this store for the FilterLink. I'm adding the contextType declaration to the FilterLink so it receives the relevant context from the Provider.

FilterLink.contextTypes = {
  store: React.PropTypes.object
};

Now that the FilterLink receives this store by context, I no longer need to pass it as a prop, so I'm removing its usage. I'm also removing the store prop from the Footer because it doesn't need to pass it down anymore.

const Footer = () => (
  <p>
    Show:
    {' '}
    <FilterLink
    filter='SHOW_ALL'
    >
    All
    </FilterLink>

    ...

  </p>
)

I'm also removing this store prop from the TodoApp component because I no longer need to pass it down to the containers.

const TodoApp = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
)

Now, instead of explicitly passing this store down by props, we pass it implicitly by context.

Let's recap how we use the context to pass this store down. We start by rendering the TodoApp inside the Provider component we defined above. The Provider component just renders whatever you pass through it. In this case, it renders its children or the TodoApp component. However, it also provides the context to any components inside it including grandchildren.

The context contains just one key called the store. It corresponds to the store we passed as a prop to the Provider component.

class Provider extends Component {
  getChildContext() {
    return {
      store: this.props.store
    }; 
  }

  render() {
    return this.props.children;
  }
}

We pass this store to the Provider component in our render call and make it available to child components by defining the getChildContext with the store key pointing to that prop.

ReactDOM.render(
  <Provider store={createStore(todoApp)}>
  <TodoApp />
  </Provider>,
  document.getElementById('root')
);

It is essential that the getChildContext is matched by childContextTypes where we specify that the store key has propType of object. Note that the childContextTypes definition is absolutely required if you want to pass the context down the tree.

Provider.childContextTypes = {
  store: React.PropTypes.object
};

The benefit is that we don't need to pass this store through the intermediate components. Instead, we can declare the context types on the container components that need access to the store so that they can retrieve it from the context instead of retrieving it from the props.

The context creates something like a wormhole between the VisibleTodoList component that reads the context and the Provider that provides the context. This wormhole is only enabled because the context types declared on the VisibleTodoList include this store that is defined in child context types of the Provider component.

VisibleTodoList.contextTypes = {
  store: React.PropTypes.object
};

The AddTodo is another component that needs access to this store. It also opts into receiving it in the context by specifying the context types. This is why, in addition to props, it receives a second argument, which is the context. I'm using the destruction syntax to grab this store from the context here.

AddTodo.contextTypes = {
  store: React.PropTypes.object
};

The context works at any depth, so it is not necessary to put context types on the Footer. The FilterLink is the component that directly uses the context, so this is the component that has to specify the context types so that it can use this store by reading it from the context.

Context is a powerful feature, but in a way it contradicts the React philosophy of the explicit data flow. The context essentially allows global variables across the component tree. But global variables are usually a bad idea. Unless you're using it for dependency injection, like here when we need to make a single object available to all components, then probably you shouldn't use context.

Finally, the context API is not stable in React. It has changed before, and it is likely to change again. Try your best not to rely on it too much.

25. Passing the Redux Store Down with Provider from React-Redux

Watch this lesson

In the previous session, we implemented the Provider component that uses the react advanced context feature to make this tool from the props available to every component in our app.

If we pass it through the Provider, we can read it in any other component from the context, which is really convenient for the container components. In fact, this is so convenient that you don't need to actually write the Provider yourself, because it is included in a special library called React-Redux.

Note that it is not the same as Redux. This is a different library. These are react bindings to the Redux library. You can import the Provider by destructuring the react-redux global object in JS bin, or if you use Babel, and something like NPM, you can import Provider with the braces, because it's a named expert from React-Redux package. Or if you write ES5 code, you can write var Provider = require('react-redux').Provider;

const { Provider } = ReactRedux;
// import { Provider } from 'react-redux';
// var Provider = require('react-redux').Provider;

Just like the Provider we wrote before, the Provider that comes with react-redux exposes this store you passed through. There's a prop on the context so the components can specify the contextTypes, and then use this context store to subscribe to the store updates and dispatch actions.

26. Generating Redux Containers with Connect from React-Redux for VisibleTodoList

Watch this lesson

In the previous lesson, I added ReactRedux bindings to the project and I used a Provider component from ReactRedux to pass this store down the context so that the container components can read the store from the context and subscribe to these changes. All container components are very similar.

They need to re-render when the store state changes, they need to unsubscribe from the store when they amount and they take the current state of the Redux store and use it to render the presentational components with some props that they calculate from the state of this store, and they also need to specify the contextTypes to get this store from the context.

I'm going to write this component in a different way now. I'll declare a function called mapStateToProps which takes the redux store state and returns the props that I need to parse through the presentation to do this component, to render it with the current state.

In this case, there is a single prop called todos. I copy-paste this expression to the mapStateToProps function. It returns the props that depend on the current state of the redux store. In this case, this is just the todos prop.

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(
      state.todos,
      state.visibilityFilter
    )
  };
};

I'm creating another function that I call mapDispatchToProps. It accepts the dispatch method from this store as the only argument and returns the props that should be passed through the TodoList component and that depend on the dispatch method.

The only prop that uses store.dispatch is called onTodoClick. Some copy-paste onto the click, into mapDispatchToProps. Now that I don't have the reference to this store here anymore. Instead, I'm changing it to use the dispatch, which is provided as an argument to mapDispatchToProps.

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
        dispatch({
        type: 'TOGGLE_TODO',
        id
      })
    }
  };
};

I will add some punctuation to make it appear easier on my eyes. onTodoClick ease of function that accepts the id of the todo, and dispatches an action. Now, I've got two different functions.

The first one maps the redux store state to the props of the TodoList component that are related to the data from the redux store. The second function maps the dispatch method of this store to the callback props of TodoList component. It specifies the behavior which callback prop dispatches which action.

To gather this, your function has described a container component so well that instead of writing it, I can generate it by using the connect function provided by ReactRedux library. If you use Babel and NPM, you will likely input it like this instead. Don't forget the curly braces.

const { connect } = ReactRedux;
// import { connect } from 'react-redux'

Now, instead of declaring a class, I'm going to declare a variable. I will call the connect method to obtain it. I'm passing mapStateToProp as the first argument and mapDispatchToProps as the second argument. Notice that this is a curried function, so I have to call it once again. This time, I parse the presentational component that I wanted to wrap and pass the props too.

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

The connect function will generate the component, just like the one I previously wrote by hand. I don't need to write the code to subscribe to this store or to specify the context types, because the connect function takes care of that.

Now, let's recap how to generate the container component using the connect function. First, I'll write a function called mapStateToProps that takes the state of the redux store and returns the props for the presentational component calculated from it.

These props will be updated anytime the state changes.

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(
      state.todos,
      state.visibilityFilter
    )
  };
};

Next, I write a function that I call mapDispatchToProps. It takes these store's dispatch method as its first argument. It returns the props that used the dispatch method to dispatch actions, so it returns the callback props needed for the presentational component.

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch({
        type: 'TOGGLE_TODO',
        id
      });
    }
  };
};

To create the container component from them, I import connect from the ReactRedux library and I call it passing mapStateToProps as the first argument and mapDispatchToProps as a second argument.

Finally, I close the function called Paren and I open another paren, because this is a curried function and it needs to be called twice. The last argument is the presentational component that I want to connect to the redux store.

The result of the connect call is the container component that is going to render my presentational component. It will calculate the props to pass through the presentational component by merging the objects returned from mapStateToProps, mapDispatchToProps, and its own props.

27. Generating Redux Containers with Connect from React-Redux for AddTodo

Watch this lesson

In the previous lesson, we used the connect function from ReactRedux bindings library to generate the container component that renders our presentational component. I specify how to calculate the props to inject from the current Redux store state and the callback props to inject from the dispatch function on the Redux store.

Normally, I would keep these functions, called mapStateToProps and mapDispatchToProps, but I'm working in a single file right now. I need to write these functions for if your other container components, so I'm going to rename them to something more specific, mapStateToTodoListProps and mapDispatchToTodoListProps, which you don't have to do in your code if you keep every component in its own file.

I will also remove the line breaks here to make it clear that these functions are only relevant for generating this particular container component.

Now I'm scrolling up to the AddTodo component, which is not clearly presentational or a container component. However, it uses this store. It reads this store from the context to dispatch an action when the button is clicked. It has to declare the context types to be able to grab this store from the context.

const mapStateToTodoListProps = ( ... ) => { ... }
const mapDispatchToTodoListProps = ( ... ) => { ... }

Context is an unstable API, so it's best to avoid using it in your application code. Instead of reading this store from the context, I will read the dispatch function from the props because I only need the dispatch here. I don't need the whole store.

I will create a container component with connect that will inject that the dispatch function as a prop. I will remove the contextTypes because the component generated by connect function will take care of reading this store from the context.

Because I changed the AddTodo declaration from the const to the let binding, I can reassign it now so that the consuming component does not need to specify the dispatch prop because it will be injected by the component generated by the connect call.

AddTodo = connect(

)

The first argument to the connect function is mapStateToProps, but there aren't any props for AddTodocomponent that depend on the current state, so I return an empty object. The second argument to connect is mapDispatchToProps, but AddTodo component doesn't need any callback props. It just accepts the dispatch function itself, so I'm returning it as a prop with the same name.

AddTodo = connect(
  state => {
    return {};
  },
  dispatch => {
    return { dispatch };
  }
)(AddTodo);

Finally, I'm calling the function for a second time to specify the component I want to wrap, in this case, AddTodo itself. The generated container component will not pass any props dependent on the state, but it will pass dispatch itself as a function so that the component can read from the props and use it without worrying about context or specifying contextTypes.

However, it is wasteful to even subscribe to this store if we don't calculate any props from its state. So I'm replacing the mapStateToProps function with a null, which tells connect that there is no need to subscribe to this store.

AddTodo = connect(
  null,
  dispatch => {
    return { dispatch };
  }
)(AddTodo);

Additionally, it's pretty common pattern to inject just the dispatch function. This is why if you specify null or any false value in connect as the second argument, you're going to get dispatch injected as a prop. In fact, I can just remove all arguments here. The default behavior will be to not subscribe to this store and to inject just the dispatch function as a prop.

AddTodo = connect()(AddTodo);

Let's recap what happens to the components here. The AddTodo component that I declare accepts dispatch as a prop, but it doesn't know how to get this store. It just hopes that someone is going to pass the dispatch to it.

let AddTodo = ({ dispatch }) => {
  let input;

  return ( ... );
};

The connect code without any arguments is going to generate a container component that does not subscribe to this store. However, that will pass dispatch to the component that it wraps. In this case, it wraps my AddTodo component.

AddTodo = connect()(AddTodo);

The second connect call returns the generated container component. I'm assigning it to AddTodo. I'm reassigning the let binding the second time.

When the further code references AddTodo, it's going to reference the container component that does not need the dispatch prop and that will pass the dispatch prop to my inner AddTodo component that I don't have a reference to anymore.

const TodoApp = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
)

29. Extracting Redux Action Creators

Watch this lesson

So far we have covered the container components, the presentational components, the reducers, and the store. But we have not covered the concept of action creators, which you might see in the Redux talks and examples.

Let's consider the following example. I dispatched the ADD_TODO action from inside the button onClick handler. This is fine. However, it references the nextTodoId variable, which added there alongside the AddTodo component.

let nextTodoId = 0;
let AddTodo = ({ dispatch }) => {
  let input;

  return (
    <div>
      <input ref={node => {
        input = node;
      }} />
      <button onClick={() => {
        dispatch({
          type: 'ADD_TODO',
          id: nextTodoId++,
          text: input.value
        })
        input.value = '';
      }}>
        Add Todo
      </button>
    </div>
  );
};

Normally, it would be local. However, what if another component wants to dispatch the ADD_TODO action? It would need to have the access to nextTodoId somehow. While I could make this variable global, it's not a very good idea.

Instead, it would be best if the components dispatching the ADD_TODO action did not have to worry about specifying the id. Because the only information they really pass is the text of the todo being added.

I don't want to generate the id inside the reducer, because that would make it non-deterministic. However, I can extract this code generating the action object into a function I will call addTodo.

<button onClick={() => {
        dispatch(addTodo(input.value));
        input.value = '';
      }}>
        Add Todo
      </button>

I pass the input value to addTodo. addTodo is just the function that takes the text of the todo and constructs an action object representing ADD_TODO action. It has the type, ADD_TODO, it takes care of generating the unique id and it includes the text.

const addTodo = (text) => {
  return {
    type: 'ADD_TODO',
    id: nextTodoId++
    text
  };
};

Although extraction such functions is not required, it is very common pattern in Redux applications to keep them maintainable, so, like all these functions, action creators, and we usually place them separately from components or from reducers.

I will now extract other action creators from the components. I see that I have setVisibilityFilter dispatch here, so I will change this to call this setVisibilityFilter action creator with ownProps.filter as the argument and is going to return the action that needs to be dispatched, so I'm declaring this setVisiblityFilter function.

const mapDispatchToLinkProps = ( ... ) => {
  onClick: () => {
    dispatch(
      setVisibilityFilter(ownProps.filter)
    );
  }
}

This is what I call an action creator, because it takes the arguments about the action and it returns the action object with the type SET_VISIBILITY_FILTER and the filter itself.

const setVisibilityFilter = (filter) => {
  return {
    type: 'SET_VISIBILITY_FILTER',
    filter
  };
};

You might think that this kind of code is boilerplate and you'd rather dispatch the action in line inside the component. However, don't underestimate how action creators document your software, because they tell your team what kinds of actions the components can dispatch, and this kind of information can be invaluable in large applications.

I will now scroll down to the last place where I call dispatch with an inline action object. I will now extract that to toggleTodo action creator, to which I pass the id of the todo as the argument.

const mapDispatchToTodoListProps = (
  dispatch
) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id));
    }
  };
};

I'm now scrolling up to my action creators and I will add a new one that I call toggleTodo. It accepts the id as the argument and it returns the action of the type, TOGGLE_TODO, and this id.

const toggleTodo = (id) => {
  return {
    type: 'TOGGLE_TODO',
    id
  };
};

Let's take a moment to consider how convenient it is to have all the action creators in a single place so that I can use them from components and tests without worrying about the action's internal structure.

Know that whether you use action creators or not, the data flow is exactly the same, because I just call the action creator to get the action object and then I call dispatch just like I did before, passing the action.