Search
Search the entire web effortlessly
maxresdefault   2025 04 30T194726.875
Mastering Multiple Reducers in Redux: A Step-by-Step Guide

In the world of JavaScript development, state management is crucial for building scalable applications. Redux, a popular state management library, simplifies the process by providing a structured way to manage application state. As applications grow, so does the complexity of the state management. This is where multiple reducers come into play. In this guide, we will explore how to implement multiple reducers in a Redux application, specifically for managing different product types.

Understanding the Need for Multiple Reducers

In our scenario, we are developing an application for a shop selling both cakes and ice creams. Initially, we had a single reducer managing the sales of both products, which quickly became inefficient as the application scaled. By introducing separate reducers for cakes and ice creams, we can keep our code modular and easier to maintain.

The Single Reducer Approach

Before we delve into the multiple reducer strategy, let’s briefly review how we managed state with a single reducer. In our original setup, we defined our state as follows:

const initialState = {
    numberOfCakes: 10,
    numberOfIceCreams: 20
};

In our reducer, we used a switch case to handle actions for both cakes and ice creams:

switch (action.type) {
    case 'BUY_CAKE':
        return {
            ...state,
            numberOfCakes: state.numberOfCakes - 1
        };
    case 'BUY_ICE_CREAM':
        return {
            ...state,
            numberOfIceCreams: state.numberOfIceCreams - 1
        };
    default:
        return state;
}

This approach works fine for a small-scale application, but as we add more products, the reducer grows increasingly complex and harder to manage. Hence, the need for multiple reducers emerges.

Implementing Multiple Reducers

The first step in implementing multiple reducers is to create individual states for each product. By splitting our reducer logic, we can create a more focused and manageable codebase.

Step 1: Define Initial States

We begin by defining two separate initial states, one for cakes and one for ice creams:

const initialCakeState = {
    numberOfCakes: 10
};  
const initialIceCreamState = {
    numberOfIceCreams: 20
};

Step 2: Create Individual Reducers

Next, we create two reducers: one for managing the cake state and the other for the ice cream state. Each reducer is responsible only for the specific slice of state it manages.

Cake Reducer

const cakeReducer = (state = initialCakeState, action) => {
    switch (action.type) {
        case 'BUY_CAKE':
            return {
                ...state,
                numberOfCakes: state.numberOfCakes - 1
            };
        default:
            return state;
    }
};

Ice Cream Reducer

const iceCreamReducer = (state = initialIceCreamState, action) => {
    switch (action.type) {
        case 'BUY_ICE_CREAM':
            return {
                ...state,
                numberOfIceCreams: state.numberOfIceCreams - 1
            };
        default:
            return state;
    }
};

Step 3: Combine Reducers

Now that we have separate reducers, we need a way to integrate them. Redux provides a combineReducers utility to easily compose multiple reducers into a single reducer function. Here’s how we implement it:

import { combineReducers } from 'redux';

const rootReducer = combineReducers({
    cake: cakeReducer,
    iceCream: iceCreamReducer
});

Step 4: Creating the Redux Store

After managing the combined reducers, we can now create the Redux store. Here’s how:

import { createStore } from 'redux';

const store = createStore(rootReducer);

Now, the store manages two slices of state, one for cakes and another for ice creams, which can be accessed independently.

Testing the Implementation

To confirm that our multiple reducers are working correctly, we can dispatch actions and verify the state updates accordingly. For instance, if we dispatch a BUY_CAKE action:

store.dispatch({ type: 'BUY_CAKE' });
console.log(store.getState());  // should log: { cake: { numberOfCakes: 9 }, iceCream: { numberOfIceCreams: 20 } }

Similarly, dispatching a BUY_ICE_CREAM action should update the ice cream count without affecting the cake count.

Conclusion

Utilizing multiple reducers in Redux enhances the modularity and maintainability of state management in your JavaScript applications. By isolating the state and logic for different product types, developers can ensure the application scales efficiently without convoluting the reducer’s function.

If you’re looking to take your Redux skills further, consider exploring advanced state management techniques or integrating middleware for asynchronous actions. With the right practices, you’ll be well on your way to mastering Redux in your projects!

Take the next step in your development journey and explore more advanced Redux concepts today!