Sitemap
Prabeen Bahinipati

Prabeen Bahinipati

Visual designer & web dev expert Prabeen is now diving into AI development, blending design with cutting-edge tech.

Master useReducer Without the Headache

4 min readJul 12, 2025

--

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

  1. State: In React, state refers to data that can change over time. For example, a counter’s value is a piece of state.
  2. 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 type property that describes the action.

How useReducer Works

  1. Initialisation: You start by defining an initial state and a reducer function.
  2. UsinguseReducer: You call useReducerin your component, passing in the reducer function and the initial state. This returns the current state and a dispatchfunction.
  3. 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.

Using⁣useReducer: 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 useReducer when 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), useState is often simpler and more appropriate.
  • Overhead: For very simple components, using useReducer might add unnecessary complexity.

Important Points:

  • State Management: ItuseReducer is 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 type property.
  • Initialization: Define an initial state and a reducer function before using.useReducer
  • Using⁣useReducer: Call⁣ useReducer(reducer, initialState) to get the current state and a⁣dispatch function.
  • 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.

--

--