liveBook · Manning

useReducer

As explained in React Quickly, Second Edition

useReducer is a React Hook function that manages component state by applying a reducer to the current state and an action.

A counter with increment and decrement buttons can use one state value and two actions. The buttons dispatch instructions; a reducer decides how each instruction changes the count. section 10.2

Listing 10.5 Counter component with reducer
import { useReducer } from "react";
function reducer(state, { type }) {                       #1
  switch (type) {
    case "INCREMENT":                                     #2
      return state + 1;                                   #2
    case "DECREMENT":                                     #2
      return state - 1;                                   #2
    default:
      return state;
  }
}
function Counter() {
  const [counter, dispatch] = useReducer(reducer, 0);     #3
  return (
    <section>
      <h1>Counter: {counter}</h1>
      <div>
        <button onClick={
          () => dispatch({ type: "INCREMENT" })           #4
        }>
          Increment
        </button>
        <button onClick={
          () => dispatch({ type: "DECREMENT" })           #4
        }>
          Decrement
        </button>
      </div>
    </section>
  );
}
function App() {
  return <Counter />;
}
export default App;

In this counter, `dispatch({ type: "INCREMENT" })` asks the reducer to return `state + 1`. The decrement action returns `state - 1`. section 10.2

`const [state, dispatch] = useReducer(reducer, initialState)` starts with an initial state and supplies a dispatch function. Calling `dispatch` with an action passes that action and the current state to `reducer`, which returns the next state. Unlike a `useState` setter, dispatch tells the reducer what happened rather than directly supplying the replacement value. section 10.2

Keep a loader's state together

A loader needs a status, result, and error. Instead of coordinating separate setters when a request fails, hold these values in one state object. Actions such as `LOADING`, `FAILURE`, and `SUCCESS` let the reducer update the object for each event; failure and success actions can carry an error or result as their payload. Define each transition carefully: the illustrated reducer spreads the previous state, so an old result or error remains unless a case clears it. section 10.2.1 section 7.1.2

function reducer(state, { type, payload }) {
  switch (type) {
    case "INITIALIZE":
      return {
        status: "INITIALIZE",    #1
        result: null,            #1
        error: null,             #1
      };
    case "LOADING":
      return {
        ...state,
        status: "LOADING",       #2
      };
    case "FAILURE":
      return {
        ...state,
        status: "FAILURE",       #3
        error: payload,          #3
        };
    case "SUCCESS":
      return {
        ...state,
        status: "SUCCESS",       #4
        result: payload,         #4
      };
  }
}

The reducer switches on the action type and returns an object for each loader transition. Compare which fields each case resets, preserves, or replaces. section 10.2.1

Reach for `useReducer` when related values and their transitions become difficult to manage with separate `useState` calls. It is not required for every state update: a simple counter can use either hook. In a task manager, moving from `useState` to a reducer became convenient as the state grew more complex. section 7.1.2 section 13.7

How React Quickly, Second Edition covers it

How deep it goes
Works from the hook signature and counter to a loader reducer with action payloads; does not descend into React internals.
Examples
Uses an increment-and-decrement counter, a data loader with success and failure states, and a task manager.
What it assumes
Builds on useState and functional components while introducing reducers, dispatch, and actions through a counter.
What you can do after
Build it from scratch to manage a component's related state with a reducer, initial state, and dispatched actions.
How it connects
Relates useReducer to useState, actions, reducer functions, interdependent state, and immutable state updates.

Also explained in

Compare how 3 books explain useReducer →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React Quickly, Second Edition. The section links point to the parts of the book it draws on.