As a personal preference I have always been concerned about the decoupling of the reducer function being in a separate place instead of inside of the action.
Especially I find the switch statement within the reducer aesthetically disturbing.
Solution to both of my problems is presented as below:
It is actually a pretty simple concept, and helps us reducing some clutter (at least in my opinion). Best part is, as you can see from the example, it can live side by side with the original approach recommended by the ngrx.io documentation.
Part 1: Defining a Custom Action Interface
Here we are defining a very simple custom interface to our own action type.
The member “feature” is simply the representative of the feature action belongs to, such as counter, user, etc. I will get back to this member in the reducer function again with the reducer part of the document.
The member “reducer” is the reducer function we use in our reducers.
Part 2: Defining the Actions
Here we are implementing our custom action interface, the “ReducingAction”.
As the example, “UserSet” action will set the “User” feature of the “State” to the content of the payload when it is dispatched.
Part 3: Defining Reducer
Reducer function is very very simple. No comprehensive switch statement either. If the action passed to this reducer function has a feature element and that feature element is equal to the current reducers feature setting the reducer will return the result of the reducer function of the action.
I have mentioned in the “Part 1” of this document that we will come back to this feature flag. So let’s dive a little more into this concept.
Since at every iteration NGRX calls all the reducers which are defined in the map of the StoreModule import, in order to avoid multiple calls to reducer function of the action we compare the “feature” flag in the reducer.
This is only necessary to avoid multiple calls to the action’s reducer function.
Even though we had to use an if statement it is still much simpler.
Part 4: (Very Simple) Performance Test
I have implemented the same project in the traditional fashion (e.g. without ReducingAction) to be able to compare the results.
In the StackBlitz application you can click to the test button, and you will see some performance results. This test dispatches two different actions 1000 times for 10 iterations. I have actually run these tests in the both types of apps (e.g. with ReducingAction and without ReducingAction).
Results are as below:
Surprisingly, up to 1000 consecutive dispatches, this approach is performing even better than the original approach. This is surprising (to me) because I was expecting that generating new objects from classes would have slowed down.
On the other side, if you dispatch much more actions, e.g. 10K or more, comparative performance starts to degrade.
As usual your mileage might vary.
Please feel free to let me know if you give it a try or if you have comments.