useState and useReducer are two ways to hold state in a React component, and they are interchangeable. useState is simpler for one independent value, while useReducer moves related update logic into a single reducer function. The deciding factor is how many updates depend on each other.
The core difference
useState spreads update logic across event handlers. useReducer pulls that logic out of the component into one pure function that decides every next state.
| Factor | useState | useReducer |
|---|---|---|
| Code size | Less upfront | More boilerplate, less when many handlers repeat |
| Readability | Clear for simple values | Clearer for many related transitions |
| Debugging | Harder to trace which call changed state | One place to log every action |
| Testing | Usually tested through the component | Reducer can be tested in isolation |
Neither is faster than the other. Both sit on the same state system, so the choice is about structure, not performance.
When useState is enough
A single counter that only increments is a clear useState case. The update logic is one line, so a reducer would add ceremony without benefit.
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}Clicking the button increases count by one. There is one value, one handler, and no dependency between separate pieces of state. Two values that update independently also fit useState, as long as neither update reads the other.
When useReducer earns its keep
A form with several fields that reset together shows the reducer advantage. Resetting all fields is one action, not several setter calls.
import { useReducer } from "react";
const initial = { name: "", email: "" };
function reducer(state, action) {
switch (action.type) {
case "changed": return { ...state, [action.field]: action.value };
case "reset": return initial;
default: return state;
}
}The changed action updates one field without losing the others, and reset restores the whole object in one branch. If you kept both fields in useState, reset would need two setters and the handlers would drift apart.
How to choose
- Use useState when one value changes independently and the logic is short.
- Use useReducer when several fields move together, like a form or a wizard.
- Use useReducer when many handlers update the same state in similar ways.
- Switch to useReducer when you keep introducing bugs from scattered update logic.
Debugging and testing
Debugging is where the reducer earns its keep. With useState, a wrong value can come from any handler. With useReducer, you can log every action in the reducer and see exactly which event produced the wrong state.
Because the reducer is pure, you can export it and test it without rendering the component.
A common false equivalence
useState and useReducer are not two different categories of state. useReducer is built on the same mechanism, so it is not more powerful or more correct by itself. Read how to write actions and reducers to learn the reducer side, and see useReducer explained with examples for the full workflow.
Rune AI
Key Insights
- useState fits simple independent values.
- useReducer collects related update logic into one pure function.
- Reducers help with debugging and testing.
- The two Hooks are equivalent and can be converted.
- Start with useState and upgrade when updates tangle.
Frequently Asked Questions
Can I use useState and useReducer in the same component?
Are useState and useReducer equivalent?
Does useReducer make my component faster?
Conclusion
useState is the default for one independent value, and useReducer is the upgrade when several values move together or update logic becomes hard to trace. Start with useState and switch only when the update code gets tangled.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.