redux concept over implementation

Redux. Concept over implementation

Since the concept of adapting MV* architectures to JavaScript never felt quite right, I started dabbling with various Flux implementations. Subsequently I got drawn towards Redux, which in my mind took all the good parts and combined them into a lightweight and easy-to-use solution.

From the moment I started doing JavaScript the concept of adapting MV* architectures to front-end apps never felt quite proper. Some time ago I started looking into all those new Flux-based architectures to use with fresh projects. Starting with the standard Flux library from Facebook, I moved through Reflux, Alt.js and few others. After I finally settled down on the former, I got inspired by all the talk about Redux to examine yet a new approach.

Case against Flux

Why didn’t I just stick with the standard one, why not just keep Flux? I found that while it delivers on the one-way flow it’s way less simple than advertised. Despite having many good concepts of Stores and Actions, the amount of code and understanding that needs to go in properly connecting them is just too much. Especially when multiplied and coupled with Dispatchers along with all other necessary steps and boilerplates to connect everything into a working structure.
Redux, in my opinion, uses some of these concepts but offers them in a much simpler way.

Its three main rules represent the three most important advantages it has. Not all of them are Redux-exclusive but combined they make a hell of a good solution.

Single source of truth

“Single source of truth” is telling us that the whole application has just one state tree. It’s probably the biggest pro for a couple of reasons. Firstly, imagine how easy it’s to hydrate it with data prepared on the backend. You send the app along with all of the initial information, without having to calculate all of that by the user’s browser, so they get instant access to everything.

Another thing is developing or debugging longer, more complex flows, e.g. adding an offer on a confidentials site. Usually it’s clicking a couple of buttons and entering few random strings of text everytime it crashes or after we write the logic for the next step. What most of us probably did before was adding some temporary logic that skips all of that to the right step. In Redux we can just populate the necessary part of the tree with proper data, because certain state equals the step the app should be in. This seems like entering a lot of data as well, but keep in mind that for Redux apps, with just a single state tree, we usually need to design the data structures early on, so we probably already have those mock ups somewhere to use.

I’ve mentioned that we need to have a well-thought-of data structure. For me it’s another important advantage. It forces a good architecture of the app, and all of its components need to be planned, along with how it should scale. It requires a level of understanding how to build proper flat data structure, which in turn makes it easier to manage new features. One notable helper library here is Normalzr. Not diving in the specifics, it allows to create a schema and given a nested object tree it outputs a nice, flat structure.

Immutable state

The second pillar of Redux is the immutability of the state. The only way to change its data is to dispatch an action that describes what happened in the app. This ensures that the flow of changes is not random, and can be easily traced.

Pure functions

The last rule is that most of Redux components use pure functions. Not only does it enhance code readability without having to follow multiple side-effects happening in ever-branching methods, but it also makes the testing significantly simpler. The only thing to do is to provide an input to a function and then to check if we have a desired output. Usually this prevents a situation where we need to mock a lot of complicated things to build a complete test environment.

Application flow

I don’t want to elaborate on the different components that Redux is build of. It has truly one of the best documentations I’ve seen, and actually read, in years. It explains with some nice examples all of the things that are happening in the flow and provides some nice tips and good practices to keep in mind when creating your own apps. I will just show you how easy the complete flow is.
Whole thing starts with the dispatching of an action (which is a plain object) returned by an action creator. That action is describing for a reducer what happened, so it can prepare a new state accordingly. In the last step the new state is being saved by the store. One thing you can add to that is connecting some middlewares between the action creators and returning the action object itself to accomodate asynchronyous flow (like API requests, etc) or extend the app, e.g. to log every performed action, thus allowing everything that happens to be easily traced.

standard Redux application flow

Standard Redux application flow

Conclusion

What draws me to Redux is that, in words of its creator, it’s not another derivate of Flux, but instead a project that’s inspired by it. It uses some concepts that are already introduced and accepted by the majority of the community (one-way flow, actions, immutability, etc.) and offers them in a simple package that you can use once you get to know just few basic rules.

Moreover, it feels less like a complete implementation and more like a good flow concept to base your logic on. Apart from few crucial parts, like the fact that an action has to be a plain object or that a reducer is a pure function, the rest is up to you. Good example is that the state tree can be constructed in any way you imagine, starting from standard JavaScript objects or arrays up to some Immutable.js data structures.

All of this gives some hope that there’s a chance it’ll stick around for some time, which in today’s world of ever-changing JavaScript frameworks and libraries is probably the most important thing. Considering how easy and flexible it is to implement I feel like Redux might be a safe bet if you want to move towards functional programming and away from standard MV* approaches.

Subscribe to our newsletter
Menu