Redux is a library that recently got adopted by a lot of developers and companies to build rich UI applications. Redux rethinks an older library called Flux. I won’t bother you about the principals of Redux and so on, you can go to the main website and read them over there.

What I want to share is some tweak that I learned by developing using this library.

Multiple reducers

Assuming you all know what reducers are and you have a big application, you eventually use combineReducers to put all together all your reducers and create - what the official documentation calls - the rootReducer that you have to pass when you create the store.

1
2
3
4
5
6
// Use ES6 object literal shorthand syntax to define the object shape
const rootReducer = combineReducers({
theDefaultReducer,
firstNamedReducer,
secondNamedReducer
});

There’s also a chapter of how to go beyond the combineReducers, you can access to it here.

What’s the documentation doesn’t say clearly is that you can use combine the reducers to create also nested reducers.

You all know that the shape of the store is defined by the structure of your reducers, so each reducer can be responsible of handling each part of the state.

I will show this concept with and example.

Example - User Information

Let’s say that you want to store the information of the users inside your Redux store, and the shape of it will be something like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
// ...
products: {
// ...
},
cart: {
// ...
}
user: {
details: {
firstName: "Micheal",
lastName: "Jackson",
email: "m.j@gmailx.com",
eyes: "2",
description: "I am tall and white",
availability: "Every day"
},
settings: {
backgroundColor: "#fff",
receiveNotification: true,
categories: ['white', 'black', 'dance', 'sing']
}
}
}

Your redux store, other than this slice of user, will have also other slices; so other reducers.
In a ideal world you will have yours reducers imported and built in this way

1
2
3
4
5
6
7
8
9
10
import user from 'src/reducers/userReducer'
import cart from 'src/reducers/cartReducer'
import products from 'src/reducers/productsReducer'
import { combineReducers } from 'redux'

export default combineReducers({
user,
cart,
products
})

As you can see it’s a simple object. But, if you changed just one value inside the array categories, your reducer will be quite complicated because you have to maintain intact the rest of the state.

What if I told you can create nested reducers

Exactly! You can create reducers that will be responsible of a subsection of the parent reducer!

Let’s create a reducer responsible of the settings and a reducer responsible of the details

1
2
3
4
5
6
7
8
9
10
// userDetailsReducer.js

export default function userDetailsReducer (state = {}, action) {
return state
}

// userSettingsReducer.js
export default function userSettingsReducer (state = {}, action) {
return state
}

Now, the new userReducer will be something like this. We will use combineReducers to create a new reducer using the other two reducers that we just create

1
2
3
4
5
6
7
8
9
// userReducer.js
import details from './userDetailsReducer'
import settings from './userSettingsReducer'
import { combineReduers } from 'redux'

export default combineReducers({
details,
settings
})

You want to have a reducer responsible of the categories? You can follow the same pattern but bear in mind that if you did that, you would need make also backgroundColor and receiveNotification reducers!

Let’s see

1
2
3
4
// settingsCategoriesReducers.js
export default function settingsCategoriesReducers (state = {}, action) {
return state
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// userSettingsReducer.js
import categories from './settingsCategoriesReducers'

// @reducer
function backgroundColor (state = {}, action) {
return state
}

// @reducer
function receiveNotification (state = {}, action) {
return state
}

export default combineReducers({
backgroundColor,
receiveNotification,
categories
})

That’s how you create nested reducers. It’s easy and the separation of concerns is more granular and easier to understand.