0
0
ReactComparisonBeginner · 4 min read

When to Use useReducer vs useState in React: Key Differences

Use useState for simple state updates like toggles or single values. Choose useReducer when state logic is complex, involves multiple sub-values, or depends on previous state, as it centralizes updates and makes them predictable.
⚖️

Quick Comparison

Here is a quick side-by-side look at useState and useReducer to understand their main differences.

FactoruseStateuseReducer
Complexity of stateBest for simple or primitive stateBest for complex or nested state
State updatesDirect setter functionDispatch actions to reducer function
State logicInline or simple logicCentralized logic in reducer
PerformanceSufficient for most casesBetter for frequent or complex updates
ReadabilityEasy for small statesClearer for complex state transitions
DebuggingLess structuredEasier to trace actions and changes
⚖️

Key Differences

useState is a React hook designed for managing simple state values like strings, numbers, or booleans. It provides a setter function to update the state directly, making it very straightforward for small or isolated pieces of state.

In contrast, useReducer is suited for more complex state management where the state might be an object or array with multiple properties. It uses a reducer function that takes the current state and an action, then returns a new state. This pattern centralizes state update logic, making it easier to handle multiple related state changes and keep the code organized.

Another difference is that useReducer can improve performance when state updates depend on previous state or when many state transitions happen, because it avoids recreating functions on every render and groups updates logically. It also makes debugging easier by tracking dispatched actions.

⚖️

Code Comparison

jsx
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}

export default Counter;
Output
A simple counter showing the current count and two buttons to increment or decrement the count.
↔️

useReducer Equivalent

jsx
import React, { useReducer } from 'react';

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>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

export default Counter;
Output
A simple counter showing the current count and two buttons to increment or decrement the count.
🎯

When to Use Which

Choose useState when:

  • Your state is simple, like a single value or a few independent values.
  • You want quick and easy state updates without extra setup.
  • Your component logic is straightforward without complex state transitions.

Choose useReducer when:

  • Your state is complex, such as objects or arrays with multiple related values.
  • You have multiple ways to update state that depend on previous state.
  • You want to keep state update logic centralized and easier to maintain.
  • You need better performance or debugging for frequent or complex state changes.

Key Takeaways

Use useState for simple, direct state updates.
Use useReducer for complex state logic and multiple related updates.
useReducer centralizes state changes making code easier to maintain and debug.
Choosing the right hook improves code clarity and performance.
Start simple with useState, switch to useReducer as complexity grows.