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 addaction that adds arbitrary amounts from an input.
- Split reducer into smaller functions for readability.