React Hooks In DepthLesson 3.3
useReducer hook: managing complex state logic
useReducer syntax, reducer function, action object, dispatch, when to prefer over useState, reducer vs Redux, initializer function
useReducer for Complex State
useReducer is useful when state transitions involve multiple values or complex logic. It centralizes state update logic into a single reducer function, making it predictable and testable.
Syntax
import { useReducer } from 'react';
const initialState = { count: 0, step: 1 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + state.step };
case 'decrement':
return { ...state, count: state.count - state.step };
case 'setStep':
return { ...state, step: action.payload };
case 'reset':
return initialState;
default:
throw new Error('Unknown action: ' + action.type);
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count} | Step: {state.step}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<input
type="number"
value={state.step}
onChange={e => dispatch({ type: 'setStep', payload: Number(e.target.value) })}
/>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}Prefer useReducer over useState when: you have 3+ related state values, next state depends on previous in non-trivial ways, or you want testable state logic. The reducer is a pure function — easy to unit test in isolation.
