Real World Example

Real World: Shopping cart with quantities and coupon

A cart has many actions (add, change quantity, remove, apply coupon). Keeping them in one reducer makes the logic easy to read and test.

function cartReducer(state, action) {
  switch (action.type) {
    case 'add':
      return { ...state, items: [...state.items, { ...action.product, qty: 1 }] };
    case 'setQty':
      return { ...state, items: state.items.map((i) => (i.id === action.id ? { ...i, qty: action.qty } : i)) };
    case 'remove':
      return { ...state, items: state.items.filter((i) => i.id !== action.id) };
    case 'applyCoupon':
      return { ...state, discount: action.code === 'SAVE10' ? 0.1 : 0 };
    default:
      return state;
  }
}

const [cart, dispatch] = useReducer(cartReducer, { items: [], discount: 0 });