Master useReducer Without the Headache
What is useReducer?
useReducer is a React hook that helps you manage state in your components. It is particularly useful when you have more complex state logic that involves multiple values or when the next state depends on the previous state.
Basic Concepts
- State: In React, state refers to data that can change over time. For example, a counter’s value is a piece of state.
- Reducer Function: This is a function that determines how the state should change in response to an action. It takes two parameters:
The current state.
An action that describes what happened (like “increment” or “decrement”).
Action: An action is an object that tells the reducer what to do. It usually has a
typeproperty that describes the action.
How useReducer Works
- Initialisation: You start by defining an initial state and a reducer function.
- Using
useReducer: You calluseReducerin your component, passing in the reducer function and the initial state. This returns the current state and adispatchfunction. - Dispatching Actions: When you want to change the state, you call the
dispatchfunction with an action. The reducer function then processes this action and returns the new state.
Example Explained Step-by-Step
Let’s revisit the counter example and break it down further:
import React, { useReducer } from 'react';Initial State: We start with an object that has a count property set to 0.
Reducer Function: The reducer function checks the action type:
If the action type is
'increment', it returns a new state object with the count increased by 1.If the action type is
'decrement', it returns a new state object with the count decreased by 1.If the action type is unknown, it throws an error.
UsinguseReducer: Inside the Counter component, we call useReducer(reducer, initialState). This gives us:
state: The current state (initially{ count: 0 }).
dispatch: A function we can call to send actions to the reducer.
Rendering the Component: We display the current count and provide two buttons:
The “+” button calls
dispatch({ type: 'increment' })when clicked, which tells the reducer to increase the count.The “-” button calls
dispatch({ type: 'decrement' }), which tells the reducer to decrease the count.
Real-Time Example: Shopping Cart
Imagine you are building a shopping cart feature for an e-commerce website. The cart can have multiple items, and you need to manage the state of the cart, including adding items, removing items, and updating item quantities.
Step 1: Define the Initial State
The initial state of the shopping cart might look like this:
const initialState = {
items: [], // Array to hold cart items
}Step 2: Create the Reducer Function
The reducer function will handle different actions related to the shopping cart. Here’s how you can define it:
const reducer = (state, action) => {
switch (action.type) {}
}Step 3: Using the Reducer in a Component
Now, let’s see how to use this reducer in a React component:
import React, { useReducer } from 'react';Explanation of the Example
Initial State: The initial state contains an empty array for items and a total amount of 0.
Get Prabeen Bahinipati’s stories in your inbox
Join Medium for free to get updates from this writer.
Reducer Function: The reducer function handles three actions:
ADD_ITEM: Adds an item to the cart or updates the quantity if it already exists.
REMOVE_ITEM: Removes an item from the cart and updates the total amount.
CLEAR_CART: Resets the cart to its initial state.
Dispatching Actions: The component uses the dispatch function to send actions to the reducer when items are added, removed, or the cart is cleared.
Importance of the Reducer Function
- Centralised State Management: The reducer function centralizes the logic for updating the state, making it easier to understand how state changes occur.
- Predictability: Since the state transitions are handled in one place, it becomes easier to predict how the state will change based on different actions.
- Debugging: It simplifies debugging because you can easily trace how actions affect the state.
When to Use useReducer
- Complex State Logic: Use
useReducerwhen your component has complex state logic that involves multiple values or when the next state depends on the previous state. - Multiple Actions: It’s beneficial when you need to handle multiple actions that affect the state in different ways.
When Not to Use useReducer
- Simple State Management: If your state management is straightforward (like toggling a boolean or managing a single value),
useStateis often simpler and more appropriate. - Overhead: For very simple components, using
useReducermight add unnecessary complexity.
Important Points:
- State Management: It
useReduceris used to manage complex state in functional components. - Reducer Function: A function that takes the current state and an action to return a new state.
- Action: An object that describes what happened, typically with a
typeproperty. - Initialization: Define an initial state and a reducer function before using.
useReducer - Using
useReducer: CalluseReducer(reducer, initialState)to get the current state and adispatchfunction. - Dispatching Actions: Use the
dispatchfunction to send actions to the reducer for state updates. - Clarity: Makes state changes clear and organised within the reducer function.
- Complex State Logic: Ideal for managing multiple values or when a state depends on a previous state.
- Predictability: Centralises state changes, making it easier to understand and debug.
Summary
- Reducer Function: It centralises the logic for how the state changes based on actions.
- Actions: They describe what you want to do (add, remove, clear).
- State Management: It helps manage complex state in a predictable way.




