In my new role I've been given the opportunity to really dig into React, learn a lot about it, and build an application with it. I had previously used Ngrx in Angular 2 so it was interesting to go back to the original Redux library after having used the Angular step-cousin. After a few small roadblocks the application is progressing rather smoothly, and I have to say I think Redux is pretty dang awesome.
The Original Problem
The "Mutable State Pattern"
Once upon a time I was building an AngularJs application basically alone for a client, and all of the sudden I needed to share data between two totally independent components (it what actually back when we called them controllers, but for this story I'm just going to call them components as it relates better to us today). I created an AngularJS service (which for other frameworks could really be any singleton class, one which always returns the same instance). I called it "DataHolderService", and it just held one huge object of other objects that eventually contained all of the strings and numbers, ie data, that was to be presented in the app. It got the job done actually. I would inject that service into the two components, and they could both reference the same object. I used this for a while and thought I was really clever for managing my state like this. However, in an argument against redux I was defendeding the mutable state pattern, but then my opponent presented me with this:
"When you use your mutable state pattern, when any of the properties of your state change, you don't know what changed it."
I spent a lot of time trying to think of how to disprove this statement. With my front-end frameworks I no longer needed to manually update the screen, and when one component updated the state it would render an update for other components also using that service's data. However, I got to points where the components would be rendering something weird, and I would see the state object (via console logs) with strange data in it. But then what do you do? I mean, you basically have to just backtrack through your console.log statements and try to figure out what happened. Race conditions and async stuff can make things hairy. It is for this reason that I deem the "mutable state pattern" and anti-pattern that should hardly ever be used irl. Instead, I recommend Redux. **ahhhh choir of angel begins singing because someone mentioned Redux**
The Redux Solution
Redux basically allows you extract all your data into some object (aka the store) in its own file, and for all of your [smart] components you can say, "yeah, just update your display whenever that object over there changes any of these specific properties". The component then dispatches actions (which are defined by a string, normally named type, and an object, normally called the payload). This actions are handled by one of more reducers. A reducer is usually a file one function, reduce. Reduce takes two things as inputs: the current state and your action payload that you sent in. Inside of that function is usually just one big switch statement when you switch on the type for the action you passed in. So your case statements are just the strings that give a name to the different actions being fired. And here's the kicker- each of those case statements return a new state. It's important that they don't modify the state directly because then we go back to having the same problems as in the mutable state pattern. Instead. We create a new state and return it so that we have a history, a record book that we can look back on. We can say, "Ok. The state was first this, then I did this action with these parameters, and afterwards the state became this". You can follow it back to where that action was called, and with the Redux Devtools Chrome Extension you have an amazing visualization for analyzing this history of states and actions.
Going Meta For A Second
I really believe that every application is just a reflection of data that can be represented by a bunch of strings and numbers inside of nested objects. This is why Redux's one state paradigm makes sense to me. Different components many care about different "slices" of your state, but in the end it's all part of the whole application state. I like Redux better than the Flux implementation called Flux (for the reason above, and also just because I think it's a terrible choice for a name). And if you are one of those hipsters trying to push something lightweight thing like MobX, just go home. Redux is what is needs to be and nothing more. It's a way to represent the application state and manage it as it changes. So whether you are using Angular, React, or something else, I hope you will recognize that power and elegance of Redux that that it fills your front-end development days with organization, control, and joy.
The posts on this site are written and maintained by Jim Lynch. About Jim...