useReducer & Complex State

⚛️ ReactLesson 11Intermediate

useReducer is an alternative to useState for managing complex state logic. It follows the Redux pattern: dispatch an action → reducer computes new state. Ideal when multiple state values interact.

1 useReducer Pattern
React — useReducer
import { useReducer } from "react";

// Reducer — pure function: (state, action) => newState
function cartReducer(state, action) {
  switch (action.type) {
    case "ADD_ITEM":
      const exists = state.items.find(i => i.id === action.item.id);
      if (exists) {
        return { ...state, items: state.items.map(i =>
          i.id === action.item.id ? { ...i, qty: i.qty + 1 } : i
        )};
      }
      return { ...state, items: [...state.items, { ...action.item, qty: 1 }] };

    case "REMOVE_ITEM":
      return { ...state, items: state.items.filter(i => i.id !== action.id) };

    case "CLEAR":
      return { items: [] };

    default:
      return state;
  }
}

function Cart() {
  const [state, dispatch] = useReducer(cartReducer, { items: [] });

  const total = state.items.reduce((sum, i) => sum + i.price * i.qty, 0);

  return (
    <div>
      {state.items.map(item => (
        <div key={item.id}>
          {item.name} × {item.qty}
          <button onClick={() => dispatch({ type: "REMOVE_ITEM", id: item.id })}>Remove</button>
        </div>
      ))}
      <p>Total: ${total.toFixed(2)}</p>
      <button onClick={() => dispatch({ type: "CLEAR" })}>Clear Cart</button>
    </div>
  );
}
2 Code Challenge
Challenge: Implement a traffic light component using useReducer. Actions: NEXT cycles through Red → Green → Yellow → Red. Display the current color and a "Next" button.