useReducer

Keep every change to complex state in one tested function.

When state changes in several ways, such as a cart where you add, remove and clear items, put every change in one function called a reducer. It takes the current state and an action, and returns the new state.

Expected output
Pen x2, Book x1
1
60

A reducer has no React in it, so you can run and test it right here. In a component, useReducer connects it to the screen:

React (JSX)
import { useReducer } from "react";

export default function Cart() {
  const [cart, dispatch] = useReducer(cartReducer, []);
  const total = cart.reduce((sum, i) => sum + i.price * i.qty, 0);
  return (
    <section>
      <button onClick={() => dispatch({ type: "add", item: { id: 1, name: "Pen", price: 10 } })}>Add pen</button>
      <button onClick={() => dispatch({ type: "clear" })}>Clear</button>
      <p>{cart.length} items, Rs {total}</p>
    </section>
  );
}
  • Use useState for a few independent values.
  • Use useReducer when the next state depends on the previous one in several different ways.
  • Never change cart inside the reducer. Always return a new array or object.
โ† Lifting state upEffects and loading data โ†’