How to Use useReducer in React: Simple Guide with Examples
In React,
useReducer is a hook that manages state by using a reducer function and an initial state. You call useReducer with a reducer and initial state, and it returns the current state and a dispatch function to update state based on actions.Syntax
The useReducer hook takes two main arguments: a reducer function and an initial state. It returns an array with the current state and a dispatch function to send actions.
The reducer function receives the current state and an action, then returns the new state based on the action type.
javascript
const [state, dispatch] = useReducer(reducer, initialState); function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state; } }
Example
This example shows a simple counter using useReducer. The state holds a count number. The dispatch function updates the count when buttons are clicked.
javascript
import React, { useReducer } from 'react'; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state; } } export default function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </div> ); }
Output
Count: 0 (initially)
Clicking + increases count by 1
Clicking - decreases count by 1
Common Pitfalls
- Mutating state directly: Always return a new state object in the reducer instead of modifying the existing state.
- Wrong action types: Use consistent action type strings to avoid unexpected behavior.
- Forgetting to dispatch: State only changes when you call
dispatchwith an action.
javascript
/* Wrong: mutating state directly */ function reducer(state, action) { switch (action.type) { case 'increment': state.count += 1; // wrong: mutates state return { ...state }; default: return state; } } /* Right: return new state object */ function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; default: return state; } }
Quick Reference
| Term | Description |
|---|---|
| useReducer(reducer, initialState) | Hook to manage state with a reducer function and initial state |
| reducer(state, action) | Function that returns new state based on action.type |
| state | Current state value returned by useReducer |
| dispatch(action) | Function to send an action to update state |
| action.type | String describing the action to perform |
Key Takeaways
useReducer manages complex state by using a reducer function and actions.
Always return a new state object in the reducer; never mutate state directly.
Dispatch actions with a type to update state via the reducer.
useReducer returns the current state and a dispatch function.
It is useful for state logic that involves multiple sub-values or complex updates.