Skip to main content

The useReducer Hook

While useState is excellent for managing independent variables, it becomes difficult to maintain when a single component has multiple state variables that rely on complex conditional logic.

For complex state management, React provides useReducer.

The Reducer Pattern​

Instead of updating state directly by calling something like setScore(), a reducer consolidates all the state update logic into a single function outside your component.

The useReducer hook accepts two arguments:

  1. A reducer function.
  2. The initial state.

It returns the current state and a dispatch function.

import { useReducer } from 'react';

// 1. The Reducer Function
function scoreReducer(state, action) {
switch (action.type) {
case 'increment': {
return { score: state.score + 1 };
}
case 'decrement': {
return { score: state.score - 1 };
}
case 'reset': {
return { score: 0 };
}
default: {
throw Error('Unknown action: ' + action.type);
}
}
}

export default function Scoreboard() {
// 2. Initializing the Hook
const [state, dispatch] = useReducer(scoreReducer, { score: 0 });

return (
<div>
<p>Score: {state.score}</p>
{/* 3. Dispatching Actions */}
<button onClick={() => dispatch({ type: 'increment' })}>+1</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}

The reducer function must explicitly be a pure function. It should take the current state and the action as arguments, calculate the new state, and return it without mutating the existing state directly.