A look at a Redux reducer

How to use reducers in a React application

We have seen that a reducer is a function that takes a state object and an action object and returns a new state object modifying the state that was received based on the action.

It's important to notice that the state object returned by the reducer is a completely new object. The reducer doesn't modify the state that was passed in.
The reducer takes the state that was passed in, and from that state it creates a new object that incorporates changes based on the action argument.

Another point of note about reducers is that they will be called with different actions as arguments.
For example, the titleReducer could be called with an action named UPDATE_TITLE and also with another action called TURN_TITLE_GREEN.
We don't know beforehand which action will be passed in, so, inside the reducer, we need to have a way to run different code based on which action matches.

This means we need to have a conditional: if this action comes in, do this. If this other action comes in, do that.
We could use if statements as conditionals, but for code clarity it's common to use switch statements inside a reducer.

A switch statement checks if a condition is true and runs the appropriate branch.
Here's a reducer with three different outputs based on the action. If the action is TURN_TITLE_GREEN, the first case statement is executed. If the action UPDATE_TITLE comes in, the second case statement is executed.

If the action that comes in doesn't match any of our case statements, the default statement at the bottom is executed and the state is returned unchanged.

const titleReducer = (state = initialState, action) => {

  switch (action.type) {
    case TURN_TITLE_GREEN: {
      return {
        ...state,
        titleColor: 'green'
      }
    }
    case UPDATE_TITLE: {
      return {
        ...state,
        title: action.payload
      }
    }
    default: return state;
  }
}

Actions that come into a reducer are objects with a type and an optional payload properties.

The type property is mandatory, and determines the action type (TURN_TITLE_GREEN, UPDATE_TITLE, and so on).

The payload property is optional but if it exists it contains information on how to change the state.
In the case statement below, we use the action payload to set a new title on the state. action.payload here holds a string with the updated title:

case UPDATE_TITLE: {
  return {
    ...state,
    title: action.payload
  }

Also, note how we return a brand new object. In the new object we use the spread operator (...) to add the original state and after that we modify only the property affected by this particular action.
This shows that we are not modifying the state directly, we are just copying the old state into a new object, then we modify the new object, and then we return it leaving the original state unchanged.

Tomorrow we will take a look at actions and we'll see how they are structured.


Did you like this article? Share it with your friends.
I write daily about front-end and back-end web technologies.
You can receive all my articles in your inbox by subscribing to my newsletter. Just click the button below. No spam, just good, useful content. Guaranteed!

Follow me on Twitter