Reducer Functions, Actions, and Dispatch0%
Reducer Functions, Actions, and Dispatch
Beginner12 min read•Updated: Jul 11, 2026
Reducer Functions, Actions, and Dispatch
1. The Anatomy of Reducer Architecture
The reducer pattern rests on three interconnected pillars:
- 1The State: The current data snapshot of your component or feature.
- 2The Action: A plain JavaScript object describing an event that occurred.
- 3The Dispatch Function: The communication channel used to send actions to the reducer.
- 4The Reducer: The pure decision-maker function that calculates the next state.
Output
[User clicks "Enroll"]
│
▼
dispatch({ type: 'ENROLL_STUDENT', payload: { id: 42, name: 'Ananya' } })
│
▼
[Pure Reducer Function: (state, action) => newState]
│
▼
[React updates state and triggers re-render]
2. Anatomy of an Action Object
By convention across the JavaScript and React ecosystem (Flux Standard Action pattern), an action object contains:
type(Required): A descriptive string inUPPER_SNAKE_CASEordomain/eventformat stating what happened.payload(Optional): Any data required to execute the transition (e.g. an ID, an input string, an object).
JavaScript
// Examples of descriptive, semantic actions:
{ type: 'TODO_ADDED', payload: 'Master React Reducers' }
{ type: 'FILTER_CHANGED', payload: 'completed' }
{ type: 'ITEM_DELETED', payload: 104 }
{ type: 'FORM_RESET' }
3. Writing Pure Reducer Functions
A reducer must adhere strictly to the rules of pure functions:
- Zero Side Effects: Never initiate API calls, start timers, modify localStorage, or trigger random numbers inside a reducer.
- Strict Immutability: Never mutate
statein place. Always use object spread (...state) and non-mutating array methods (map,filter). - Deterministic: Given the same state and action, it must always return the exact same output.
JSX
export const initialCartState = {
items: [],
discountCode: null,
totalPrice: 0
};
export function cartReducer(state, action) {
switch (action.type) {
case 'ADD_ITEM': {
const existingIndex = state.items.findIndex(i => i.id === action.payload.id);
let updatedItems;
if (existingIndex > -1) {
// Increment quantity immutably
updatedItems = state.items.map((item, idx) =>
idx === existingIndex ? { ...item, quantity: item.quantity + 1 } : item
);
} else {
// Add new item immutably
updatedItems = [...state.items, { ...action.payload, quantity: 1 }];
}
return {
...state,
items: updatedItems,
totalPrice: updatedItems.reduce((acc, i) => acc + i.price * i.quantity, 0)
};
}
case 'REMOVE_ITEM': {
const filtered = state.items.filter(i => i.id !== action.payload);
return {
...state,
items: filtered,
totalPrice: filtered.reduce((acc, i) => acc + i.price * i.quantity, 0)
};
}
case 'APPLY_DISCOUNT': {
return {
...state,
discountCode: action.payload,
totalPrice: state.totalPrice * 0.9 // 10% off
};
}
case 'CLEAR_CART':
return initialCartState;
default:
// Return unchanged state or throw error for unrecognized actions
return state;
}
}
4. The Stability of dispatch
In React, the dispatch function returned by useReducer is guaranteed to have a stable identity across all renders.
React guarantees that dispatch will never change its reference between re-renders. This means:
- You do not need to include
dispatchinuseEffectoruseCallbackdependency arrays. - Passing
dispatchdown through props or Context will never trigger unnecessary child re-renders!
Interactive Quiz
Practice Quiz
Question 1
What two properties are standard on a Flux Standard Action object?
Question 2
What should happen if a reducer receives an unknown action type that it does not handle?
Question 3
Why is performing an asynchronous
fetch() inside a reducer function strictly forbidden?Question 4
Does the
dispatch function returned by useReducer change reference between component re-renders?Question 5
What makes reducers exceptionally easy to unit test compared to components?
Next Lesson
Managing Complex State Transitions with useReducer
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| When to Choose useReducer Over useState | Managing Complex State Transitions with useReducer |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.