Integrating Redux

You all know that Redux made the difference few years ago and now a lot of developers are starting using it (mostly together with React).
What people really miss is that Redux can be used alone inside a frameworkless project (or inside a project that has a framework/library that is not React).

I - as senior - recently decided to introduce Redux inside an enterprise project to manage the big amount of data that frontend has to deal with. One of the perks of having Redux is to have a one-way-flow to store the data, which basically sets some rules among the team and the project itself. Having rules is good. You team decide which ones and after that you are good to go.

After the integration

So, after three weeks of refactor, coding, testing, bugfix and lot of changes among the application (they were a lot, trust me), the application ended up having almost TWO HUNDRED REDUCERS, all of the them listening to the same actions. I can’t share too much about why so many, but it was due to the project needs and architecture.
The application didn’t have any subscritions to the state changes, so there wasn’t a reactive change based on the data inside the Redux store. Everything was done to manage in a clean and fixed way the data inside the application.

Even though there was no UI involved, the number of accesses done to the state was a lot! Also, the number of actions to store the data was a lot. (I did put some logging and I was impressed).

Although, there were no performance regressions inside the application.

Further optimisations

Here’s the good part of the article. Have you ever thought of importing a reducer only when is needed? I don’t think so. You might say that there’s no need because Redux is fast and you are right. However, sometimes there are cases where is better to do it. Like this one.

Redux gives us an API called replaceReducer which is basically what is needed is this case.

It’s not well documented but it gives you an idea of when to use it.

And that’s what I did inside the code! We already had code splitting inside the application. There’s a key point about this API, the next reducer that you provide will replace the old one, which means that you have to provide a new object that contains also the old reducers.

Snippets

So, let’s put all these idea together and see how this idea could be applied to a real world scenario. First of all let’s make a function that it actually create a new root reducer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// two fake reducers for starter
const foo = (state = {}, action) => state;
const bar = (state = {}, action) => state;

// or `let` if you want to stick with functional/immutability
const currentReducers = {
foo,
bar
}

export function nextReducer (newReducers) {
// make some check here, here's is done with lodash. You could extend the check
if (_.isObject(newReducers)) {
// I'd suggest the latter approach
Object.assign(currentReducers, newReducers)
// .. or
currentReducers = {
...currentReducers,
...newReducers
}
}

return combineReducers(currentReducers)
}

So we have a snippet that gives a new root reducer with the new reducers that we want. How do we use it?
Let’s suppose that we are already inside a code splitted section of the application, for example the admin section. After the import() statement, we should behave like this:

1
2
3
4
5
6
7
8
// adminReducers.js where we have the reducers for the admin section
import { sideBar } from './sidebar'
import { settings } from './settings'

export const adminReducers = {
sideBar,
settings
}

Now let’s what’s inside the page where we actually need these reducers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { nextReducer } from 'path/to/nextReducer'
import { store } from 'path/to/my/store'

import('path/to/admin/main/page', ({ renderPage }) => {
// let's request our new reducers
requestAdminReducers()
.then(({ adminReducers }) => {
const newRootReducer = nextReducer(adminReducers)
store.replaceReducer(newRootReducer)
renderPage();
})
})

function requestAdminReducers () {
return import('path/to/adminReducers.js')
}

Voila’!

Comment and share

  • page 1 of 1

Emanuele Stoppa

Programmer, Gamer and music listener


Senior UI Developer, Contractor


Dublin