Bryan García

useState or useReducer: finding the right tool for your React state

Learn when to reach for useState and when your state deserves the structure of useReducer in React.

Front-end
React
useState vs useReducer illustrated

Inside every React app, state behaves like a small stage play. It moves, shifts, improvises, and sometimes tangles itself like a headphone cable. To keep that show under control, React gives us two reliable performers: useState and useReducer.

Both manage state, but each carries its own attitude. One is straightforward and nimble; the other is structured and orchestral. Knowing when to choose one over the other can keep your components elegant instead of chaotic.

useState: the quick brush of the artist

useState is direct. It asks for so little and delivers quickly. It's ideal when your state is simple enough that you can hold it in your head without needing a whiteboard.

Use it when:

1. Your state is simple

Counters, toggles, inputs, active tabs, boolean flags.

const [isOpen, setIsOpen] = useState(false);

2. Updates are small and atomic

You're changing one thing at a time, and the component doesn't need a long decision tree to figure out what to do.

3. Your logic doesn't need a map

If you're not branching into complex conditions or chaining several updates, useState keeps everything light and readable.

useReducer: the conductor of the orchestra

useReducer steps in when your state starts to have a story. Maybe it has multiple properties, multiple types of events, or a flow that needs structure to stay predictable.

Use it when:

1. Your state is complex or multi-property

Large forms, shopping carts, nested objects, or anything where multiple variables move together.

2. You want update logic outside the component

function reducer(state, action) {
  switch (action.type) {
    case "add":
      return { items: [...state.items, action.payload] };
    case "remove":
      return { items: state.items.filter(i => i.id !== action.payload) };
    default:
      return state;
  }
}

const [state, dispatch] = useReducer(reducer, { items: [] });

3. You want predictable flow

Action → reducer → new state.

4. You expect the component to grow

When you know more actions or event types will likely be added, useReducer scales gracefully.

The golden rule

If your state is simple, use useState.

If your state has a narrative, use useReducer.