Dynamic $ngRedux Reducers
We’ve been using $ngRedux rather successfully to bind our Redux store into our Angular application. It’s a rather small library, but it does its job rather well.
We’ve written hundreds of reducers, across multiple sub-applications without issue. Until I decided to get cute. We were attempting to address our large bundle size, and decided to attempt to load our sub-applications on demand.
After solving the Angular side of it (more on this later), we had an issue with $ngRedux not properly initializing the new reducers that we pulled in from the sub-application.
The initial approach was to re-create the store, with the current store as the initial state. However, this failed to work because asynchronous actions were being handled by the reducer with the old store reference, and overriding our newly initialized store.
Looking at the git repo, I discovered that they were encapsulating the store inside the service, without exposing the object Redux proper creates. If that were the case, this would be straightforward, as Redux has the ability to dynamically add reducers.
My first thought was fork the project, and create a clone in which I could have the control. I was OK with this, as the repo has been pretty inactive.
Then one of my coworkers pointed out a fundamental aspect of Redux that I completely missed.
A reducer is a pure function.
What does this mean? It’s simply a function that takes some inputs, and returns an output, with no side-effects. Since $ngRedux ultimately has a reference to this pure function, and that reference doesn’t get replaced, all I had to simply do was give it a function that then called a function. I created a class that had a function on it that would return the result of a dynamically modified function.
As new reducers came in, I created a new reference to the inner function call using combineReducers from redux and wha-bam. Done.
Simply put, I created a pure function that calls a pure function, and returns its results.