React - useReducer & Advanced State
Overview
Estimated time: 25–35 minutes
useReducer lets you manage complex state transitions using a reducer function. It can make logic clearer than multiple useState calls.
Learning Objectives
- Understand when to choose useReducer over useState.
- Implement a reducer with actions and dispatch.
- Use lazy initialization and modularize reducer logic.
Prerequisites
- React - Props & State
- React - useEffect (optional)
Try it: Counter with useReducer
View source
const { useReducer } = React;
function reducer(state, action){
switch(action.type){
case 'inc': return { count: state.count + action.step };
case 'dec': return { count: state.count - action.step };
case 'reset': return { count: action.to };
default: return state;
}
}
function App(){
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: <strong>{state.count}</strong></p>
<button onClick={() => dispatch({type:'inc', step:1})}>+1</button>
<button onClick={() => dispatch({type:'dec', step:1})} style={{marginLeft:8}}>-1</button>
<button onClick={() => dispatch({type:'reset', to:0})} style={{marginLeft:8}}>Reset</button>
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-reducer')).render(<App />);
Syntax primer
useReducer(reducer, initialState)
returns[state, dispatch]
.dispatch({type:'inc', step:1})
sends an action to the reducer.
Common pitfalls
- Don’t mutate state in the reducer; always return a new object.
- Keep action shapes consistent; prefer a small set of clear actions.
Vocabulary
- Reducer: Pure function that calculates next state from current state and action.
- Action: Object describing “what happened” (must have
type
).
Exercises
- Add an
add
action that adds arbitrary amounts from an input. - Split reducer into smaller functions for readability.