liveBook · Manning

useReducer

As explained in React Hooks in Action: With Suspense and Concurrent Mode

useReducer is a built-in React Hook that manages component state through a reducer function and dispatched actions.

useReducer is a built-in React Hook for components whose state contains several related values or whose update logic is becoming difficult to follow. Instead of setting each value separately, the component dispatches an action; a reducer uses the current state and action to produce the next state. section 3.0 section 3.2

Use the Hook by connecting three pieces:

  • Pass a reducer and initial state to receive the current state and a dispatch function. section 3.2.3
  • Dispatch actions from event handlers instead of directly updating individual state values. section 3.2.3 section 3.4
  • Handle action types in the reducer and return a new state; use an object with type and payload for nontrivial actions. section 3.5

Managing a bookings list

A BookablesList component tracks the selected group, bookable index, bookable data, and whether details are visible. Its setup is `const [state, dispatch] = useReducer(reducer, initialState);`. A checkbox can dispatch `{ type: "TOGGLE_HAS_DETAILS" }`, while other handlers dispatch actions for switching groups or selecting bookables. React passes the action and current state to the reducer, then calls the component again with the updated state. section 3.2.3 section 3.4

Generating initial state

When initial state requires computation, pass an initialization argument and function: `const [week, dispatch] = useReducer(reducer, date, getWeek);`. The WeekPicker component uses `getWeek` to create its initial week from a date, then dispatches actions such as `PREV_WEEK` and `TODAY` for navigation. section 3.3.4 section 3.3

Listing 3.5 The BookablesList component using a reducer
import {useReducer, Fragment} from "react";                        #1
import {bookables, sessions, days} from "../../static.json";
import {FaArrowRight} from "react-icons/fa";
 
import reducer from "./reducer";                                   #2
 
const initialState = {                                             #3
  group: "Rooms",                                                  #3
  bookableIndex: 0,                                                #3
  hasDetails: true,                                                #3
  bookables                                                        #3
};                                                                 #3
 
export default function BookablesList () {
  const [state, dispatch] = useReducer(reducer, initialState);     #4
 
  const {group, bookableIndex, bookables, hasDetails} = state;     #5
 
  const bookablesInGroup = bookables.filter(b => b.group === group);
  const bookable = bookablesInGroup[bookableIndex];
  const groups = [...new Set(bookables.map(b => b.group))];
 
  function changeGroup (e) {
    dispatch({                                                     #6
      type: "SET_GROUP",                                           #6
      payload: e.target.value                                      #6
    });                                                            #6
  }
 
  function changeBookable (selectedIndex) {
    dispatch({
      type: "SET_BOOKABLE",
      payload: selectedIndex
    });
  } 
 
  function nextBookable () {
    dispatch({ type: "NEXT_BOOKABLE" });                           #7
  }
 
  function toggleDetails () {
    dispatch({ type: "TOGGLE_HAS_DETAILS" });
  }
 
  return (
    <Fragment>
      <div>
        // group picker
 
        <ul className="bookables items-list-nav">
          {bookablesInGroup.map((b, i) => (
            <li
              key={b.id}
              className={i === bookableIndex ? "selected" : null}
            >
              <button
                className="btn"
                onClick={() => changeBookable(i)}                  #8
              >
                {b.title}
              </button>
            </li>
          ))}
        </ul>
 
        // Next button
      </div>
 
      {bookable && (
        <div className="bookable-details">
          <div className="item">
            <div className="item-header">
              <h2>
                {bookable.title}
              </h2>
              <span className="controls">
                <label>
                  <input
                    type="checkbox"
                    checked={hasDetails}
                    onChange={toggleDetails}                     #9
                  />
                  Show Details
                </label>
              </span>
            </div>
            <p>{bookable.notes}</p>
            {hasDetails && (
              <div className="item-details">
                // details
              </div>
            )}
          </div>
        </div>
      )}
    </Fragment>
  );
}
#1 Import the useReducer hook.
#2 Import the reducer from listing 3.4.
#3 Specify an initial state.
#4 Call useReducer, passing the reducer and the initial state.
#5 Assign state values to local variables.
#6 Dispatch an action with a type and a payload.
#7 Dispatch an action that doesn’t need a payload.
#8 Call the new changeBookable function.
#9 Call the new toggleDetails function.

Inspect the complete BookablesList implementation, including imports, initial state, reducer setup, and state destructuring. section 3.2.3

How React Hooks in Action: With Suspense and Concurrent Mode covers it

How deep it goes
Explains reducer workflow, initialization functions, dispatch stability, and re-render cycles, without pursuing implementation internals.
Examples
Demonstrates loading posts, a counter, BookablesList interactions, and WeekPicker initialization and navigation.
What it assumes
Assumes familiarity with React function components, hooks, state, props, and event handlers.
What you can do after
Apply it via React’s useReducer Hook to build components with centralized state transitions and action-driven event handlers.
How it connects
Connects reducers with state, actions, dispatch, useState, event handlers, re-rendering, and Redux.

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 Hooks in Action: With Suspense and Concurrent Mode. The section links point to the parts of the book it draws on.