React

Reducing State

React Course

Introduction

You have probably heard about reducers before. In this lesson we are going to learn what they are, when to use them and how to use them in React with the useReducer hook.

Lesson overview

This section contains a general overview of topics that you will learn in this lesson.

  • What are reducers.
  • When to use reducers.
  • What is the useReducer hook.

What are reducers?

Reducers are pure functions that take a previous state and an action to return a new state.

The action is an object with a type property describing what the user did. This object can also contain any other properties that our reducer might need to produce the new state.

We can define a reducer that updates the state of a counter like this:

function reducer(state, action) {
  switch (action.type) {
    case "incremented_count": {
      return { count: state.count + 1 };
    }
    case "decremented_count": {
      return { count: state.count - 1 };
    }
    case "set_count": {
      return { count: action.value };
    }
    default: {
      throw new Error("unknown action: " + action.type);
    }
  }
}

Remember, reducers are pure functions so we shouldn’t mutate the state.

When to use reducers?

If a component only needs to update its state in a couple of simple ways, you don’t need to use reducers. The opposite can be said when a component has become too big, hard to read or debug because of its state logic.

By using reducers, we can separate the state logic and even store it in a different file or directory, leading to smaller components that are easier to read.

Since reducers use actions, we can easily track any state-related bugs back to the dispatched action, and because our reducers are just pure functions, we can test them in isolation.

The useReducer hook

React allows us to use reducers in our components through a hook called useReducer. This hook takes a reducer function and an initial state as arguments, then returns an array with two values: the current state and a dispatch function.

This dispatch function receives an action object as argument, which is passed to our reducer function and the returned value from it is used to update the state.

const [state, dispatch] = useReducer(reducer, { count: 0 });

function handleClick() {
  dispatch({ type: "incremented_count" });
}

Similarly to the set function in useState, React only updates the state in the next render after calling the dispatch function. Keep in mind that these functions use Object.is() to determine if the state has changed, if it hasn’t, then the component won’t re-render.

Whether you use useState or useReducer is up to you, they’re both equivalent and you might use them both in the same component.

Assignment

  1. Read through the React docs Extracting state logic into a reducer to learn more about how to use reducers in React and how to refactor useState into useReducer. Don’t forget to complete the challenges at the end.

  2. Read the useReducer React docs to learn more about this hook. Pay close attention to the troubleshooting section for common problems that you might encounter.

Knowledge check

The following questions are an opportunity to reflect on key topics in this lesson. If you can’t answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge.

Additional resources

This section contains helpful links to related content. It isn’t required, so consider it supplemental.

Support us!

The Odin Project is funded by the community. Join us in empowering learners around the globe by supporting The Odin Project!