useReducer vs useState
What useReducer does
useReducer is a React hook that lets you manage state through a reducer function.
It works like Redux:
state is not changed directly, but through an "action".
Syntax
javascript
const [state, dispatch] = useReducer(reducer, initialState);stateis the current statedispatchis a function that dispatches an "action"reducer(state, action)is a function that receives the current state and an "action" and returns the new state
Simple example
javascript
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}How it works:
- On click, React calls
dispatch({ type: "increment" }). - React calls
reducer(state, action). - The reducer returns a new state -> React re-renders the component.
How useReducer differs from useState
| Criterion | useState | useReducer |
|---|---|---|
| State type | Simple (single value) | Complex (object, array, update logic) |
| Update | setState(newValue) | dispatch({ type, payload }) |
| Update logic | Directly in the component | Moved into a separate function (reducer) |
| When to use | Simple cases (counter, form, toggle) | When state is complex or driven by different actions |
| Good fit for | Small components | Large / complex state |
| Similar to | A built-in Redux alternative | A mini-Redux inside a single component |
Comparison example
Version with useState
javascript
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);Simple, but does not scale well when the logic gets complex.
Version with useReducer
javascript
function reducer(state, action) {
switch (action.type) {
case "increment":
return { ...state, count: state.count + 1 };
case "decrement":
return { ...state, count: state.count - 1 };
case "reset":
return { ...state, count: 0 };
default:
return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });Now you can manage the logic centrally, which is convenient when there are many branches or states.
When it's better to use useReducer
Use useReducer when:
- The state is complex (for example, an object with several fields).
- Update logic depends on different action types.
- Multiple parts of the code can update the same state.
- You want to separate the logic (reducer) from the UI component.
Examples:
- A form with validation
- A multi-step process (wizard / onboarding)
- A list of items with filtering, sorting, adding, removing
A "form" example with useReducer
javascript
function formReducer(state, action) {
switch (action.type) {
case "changeField":
return { ...state, [action.field]: action.value };
case "reset":
return { name: "", email: "" };
default:
return state;
}
}
function Form() {
const [form, dispatch] = useReducer(formReducer, { name: "", email: "" });
return (
<form>
<input
value={form.name}
onChange={(e) =>
dispatch({ type: "changeField", field: "name", value: e.target.value })
}
/>
<input
value={form.email}
onChange={(e) =>
dispatch({ type: "changeField", field: "email", value: e.target.value })
}
/>
<button onClick={() => dispatch({ type: "reset" })}>Clear</button>
</form>
);
}Now you can easily extend the form, just add a new case.
Summary
| Question | Answer |
|---|---|
What does useReducer do? | Manages state through a reducer function, reacting to "actions" |
How does it differ from useState? | useState just stores a value, useReducer manages complex logic |
| When to use it? | For complex or related updates |
| When not to? | For simple numbers, strings, flags - useState is simpler |
| How is it similar to Redux? | The same "action -> reducer -> new state" principle, just local |
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.