Getting Started With Redux

Maintain Data Integrity While Your Solution Grows

Posted by Heikki Kupiainen/Oppikone on 03.07.2017 19:38:59

Why Redux?

In my previous article about combining jQuery with ReactJS I showed how to use vanilla JavaScript to create a data service and a data model for your ReactJS app. That approach, while being a simple solution to implement a data store for your app, will have its caveats when your app starts growing in size. With Redux, you can equip your application with a more robust data store without compromising integrity. In this article, I will show how to extend your ReactJS app with Redux data store.

About Events

Before getting started with Redux or event-driven programming in general, be careful not buying into hype. First of all, it is not difficult at all to implement from scratch a vanilla framework for dispatching and handling events. Please check my implementation of event framework Synchronous Dispatcher for example. If you check source code, you see that implementing Redux-style event framework is quite easy. Note that my implementation is way simpler to use than Redux as well, requiring smaller amount of code. I will show later how to implement an application wide data storage - similar to to Redux data storage but perhaps more intuitive - it's a question of taste!

You can use an application wide data storage with or without event dispatching-handling mechanism. These two design patterns can be used together or as standalone solutions.

Dangers of Event Driven Approach

There is some hype around event driven programming and its cousin, "reactive" programming (which in turn has nothing to do with React). But experience shows that using application wide events really can make code unreadable. You fire an event somewhere in your app. It will be handled somewhere else in the app. This jump destroys readability of code. You need to explicitly find the places where this event is being handled. And if the event is handled by many listeners in different parts of application - which all perform a different thing and you can't know their execution order... The cornerstones for a real disaster have already been laid! I learned dangers of event driven approach hard way already by 2010 when Adobe Flex - a predecessor of today's JavaScript-based techniques - was still hot. Adobe Flex based Mate framework providing event driven programming to ActionScript - similarly to Redux that is being mentioned often today - did not prove to be a magic bullet but a source of sorrow instead.

Bubbling Vs. Dispatching Vs. Direct Invocation

The basic idea of Redux is to ensure that your data model is consistent. If a certain data point changes we should always be sure that this data is immediately up-to-date in all sub-parts of the application. In Redux, this is achieved by dispatching actions that are then used to update states in the central data store. In my previous example, I showed how requests fired in different parts of the application would bubble upwards toward higher levels. That approach promotes modularity but it certainly has its drawbacks. Let's say that the user clicks on "Exit" button that is embedded in a component at the leaf in the component hierarchy. Now, logging out is a function typically implemented at the top level of the software. If the events must bubble through all the hierarchy before they reach their target component then we must implement quite a long chain of local listeners and dispatchers. If the event launches local variable changes on its way toward the root then it will likely cause bugs resulting from data states being out of sync in various parts of the application.

It may not be too unintuitive to come up with a solution that lets the leaf component bypass all that hierarchy and deliver the information directly to the place where it is needed. This can be done either by dispatching a global action inside the leaf component or empowering it with a direct invocation handle to the data service component. Both solutions have their pros and cons. Redux favors dispatching actions. Before discussing benefits and caveats of each solution in detail let's revise how to implement a Redux-style dispatcher mechanism!

But before we dive into different kinds of event-based solutions to transfer data inside a React (or whatever) app, you might like to view the source code of my demo implementation featuring a of bubbling type of communication between different parts of application! And if you want to learn a truly neat way to pass events in your React app, please have a look at my blog post about Synchronous Dispatcher!

Essentials of Redux

When you place your data in Redux, you start with writing an action. Action can be understood as a package that contains the payload being transferred from one place inside your App to another place. After you define the action for your data, you continue by implementing a reducer that catches the action, possibly executes some derivative functions on the data object received and finally places it in Redux data storage. Once the data is placed in Redux data storage, it can be easily made available for different parts of your application. And finally, you must remember to dispatch the data! A typical situation to dispatch your data is when you load a data object from server over an AJAX request. Loading data from server can be done either using the native fetch function or relying on some AJAX library such as Axios or jQuery.

Stay Calm and Cool With Concepts!

For someone not so familiar with html templating frameworks, data storages, dispatchers and request frameworks it's easy to mix up these concepts. Let me clarify therefore that you can combine all these things in different ways. For instance, you can skip Redux dispatcher alltogether and put your data directly into Redux data storage after loading it from server. And you can code with ReactJS without using Redux at all. In that case you can use your custom application wide data storage if you like. And you can use Redux dispatcher without using Redux data storage. Why not set up your own event framework on coffee break if you are momentarily out of tasks? And you can use Redux without using ReactJS for rendering views at all. You can code with all these frameworks using plain old good JavaScript and you can code using some other JavaScript variant such as ES6 or ES7 - in that case you must include a transpiler such as Babel in your app. You can use a package manager such as NPM to glue all these libraries together - but you don't have to do so! You can also include all these dependencies directly in browser. You can use NPM - but you can use Yarn or Bower or many alternatives as well! You can use Bootstrap with your App for html styling - but you don't have to! There are endless combinations and the world is free!

Calling a Dispatcher

I am going to hightlight integrating Redux with React by extending our Car App with a feature that allows the user to add new cars to the data model. To achieve this, we are going to implement a dispatcher mechanism in Redux way. But before we start, let's not forget to enable Redux features in your app by adding following dependencies to your main app:

import { createStore } from 'redux'
import { Provider } from 'react-redux'

Now, we are good to go. The idea is that when the user clicks on "Add Car" button, the corresponding component dispatches an "AddCar" action that enriches the data model with one more car. Then all components representing this data should be updated automatically to match the new reality.

To Be Continued...