A Detailed Study of Flux: the React.js Application Architecture

Ann
January 17, 2017

Flux is a new kind of architecture that Facebook uses when it works with React. It comes to the question of what React is. React - a popular front end technology like AngularJS - is a Javascript framework, but it is only the View layer, which is means you have only the V in the MVC - Model-View-Controller architecture. All the while you see that React is mentioned along with other frameworks, but it offers just the View. React gives you the template language and a few function hooks to render HTML. Since it is component based, you can compose an application with React, and just specify how you want your component to look like. React will keep it updated; even the underlying data changes. The core principles of React are (1) Flexibility, (2) Efficiency and (3) Declarative code. As React is flexible, you can use it in several projects, create new apps and even use it within the existing code base, without doing a rewrite.

What is Flux?

We learnt that React takes care of V or the View part in MVC. Now, what about the M or the Model part? Flux, a programming pattern takes care of the M in the MVC. It is the architecture responsible for creating data layers in JavaScript applications and building client-side web applications. Flux complements React�s Composable view components through its unidirectional data flow. You can also say that Flux is more of a pattern, than a framework and it has four main components (we will go in depth later):

  • Dispatcher
  • Stores
  • Views (React components)
  • Action

This is not like the general MVC that you see in other frameworks. But yes, there are Controllers, but they are mostly Controller views. Views are at the top of the hierarchy and they retire the data and functionality and pass them down to their children.

Flux follows the concept of unidirectional data flow making it much easier to zero in of where the error lies. The data goes through a strict pipeline through your application. React and Flux are actually two of the most popular frameworks that follow the concept of unidirectional data flow.

While React makes uses of a virtual DOM object to render changes, Flux does it differently. In Flux, the interactions with user interface will trigger a series of actions that would alter the application data. The View will get alerts on the changes.

Main Features of Flux

Flux is open source and more of a design pattern than a formal framework and you can use it immediately. What keeps it apart from other frameworks is that it is different from the MVC Design pattern.

Flux keeps code predictable when compared to other MVC frameworks. Developers can build applications without being bothered about complicated interactions between data resources.

Flux boasts of a better structured data flow � unidirectional. Being unidirectional is the central feature of Flux. The actions are propagated to the new system with regard to user interactions. You can start using Flux without using a whole lot of new code, apart from React.

Flux vs. MVC

Now that we have both MVC and Flux patterns, the next question would be which one is a better choice. Let�s go a little deeper into this:

There are different kinds of MVC patterns, but the basic concept of each one remains the same:

  • Model - Maintains the behavior & data of an application domain
  • View - The display of the model in UI
  • Controller - Uses the user input, manipulate the model & update the view

The main problem with MVC is that it doesn�t scale well for Facebook�s huge code base. Flux proved to be a better choice because it is all about tweaking the flow inside the app.

MVC has stood the test of time, and ever since its launch in 1976, it has been the favorite for many developers. Even in the recent years, developers have been using for several projects.But MVC couldn�t handle code base that Facebook needed, and hence Flux started ruling the roost. Let�s take a look at the main factors due to which Flux has an upper hand over MVC design pattern.

The Flow - Flux is quite strict about the flow of application. The data Dispatcher puts forth some strict rules and exceptions to govern the flow. There is no such thing in MVC, and the flows are implemented differently.

Unidirectional Flow in Flux - While MVCs are bidirectional in their flow, in Flux, all the changes goes in the same direction through data Dispatcher. The Store cannot change by itself, this is the same concept for all other Actions. Changes to be made have to go through the Dispatcher through Actions.

Store - While MVC cannot model single objects, Flux can do it to store any application related data.When it comes to choosing Flux or MVC, Flux would be a better choice because it is very easy to understand and works with very minimum code usage. Flux allows you to structure your app effectively.This is something to look forward to because React's programming language is integrated with a very huge code base that is seemingly endless and a huge run time complexity that developers just hate. Once you understand the cons of bidirectional data flow, it would be easier to understand why unidirectional data flow is the best. In the bidirectional data flow, you have the typical data flow � Model-View-Controller. But when applications became more complex, the Controller begins to feel the burden.

The Controller takes the huge responsibility of maintaining both the application state and the data. Also, the cascading updates makes the app really difficult to understand and debug. In the end, you have an application whose results are totally unpredictable. With unidirectional data flow, this problem is mitigated, and eventually, predictable application state is achieved. When the data flow is unidirectional, changes in the application view layer will trigger an action in the data layer. These changes will then be reflected in the View. The View does not directly affect application data.

Flux Architecture and How it Works

The components in Flux architecture interact more like EventBus and less like an MVC. As mentioned earlier, Flux is not actually a library or a framework, it is a new kind of architecture that Facebook uses internally when working with React. Hence the main function of Flux would be to complement React and promote Unidirectional Data Flow.

Flux Application Architecture

In a typical Flux architecture, you will find the following components.

Actions - Helpers that pass data to the Dispatcher

Dispatcher - Receives these Actions and broadcast payloads to registered callbacks.

Stores - Act as containers for application state & logic. The real work in the application is done in the Stores. The Stores registered to listen in on the actions of the Dispatcher will do accordingly and update the Views.

Controller Views - React Components grab the state from the stores and then pass it down to the child components.

The Controllers in the MVC and Flux are different. Here the Controllers are Controller-Views, and are found at the very top of the hierarchy. Views are React components.All the functionality is usually found within the Store. The Store is where all the work is done and tells the Dispatcher which events/actions it is listening for.

When an event happens, the Dispatcher would send the �payload� to the Store that is registered to listen for that particular action. Now it is up to the Store to update the View, which in turn triggers an action. The action to happen is also predetermined like name, type of action and so on.

The View propagates the Action though a central Dispatcher and this will be sent to various Stores. These Stores would contain an application�s business logic and other data. It updates all the Views.It works best with React�s programming style and the Store sends updates without the need to detail on how to transition views between states.

This proves that Flux pattern follows a unidirectional data flow. The Action, Dispatcher, Store and View are independent nodes with specific inputs and outputs. The data flows through the Dispatcher, the central hub, which in turn manages all the data.The Dispatcher acts as a registry with registered callbacks that the Stores respond to. Stores will emit a change which will be picked by the Controller-Views.

This is what happens when a View is propagated in this system.

This proves that there are no two-way bindings, the structure is akin to functional relative programming, and more something like flow-based programming.The dependencies that occur in the stores are kept in strict hierarchy, while the Dispatcher handles the updates. This structure also solves the problems that come naturally with two-way binding.To create a Dispatcher you need to bring the Dispatcher from the Flux. Do this by typing Dispatcher.js

A Detailed Overview of Dispatcher

The Dispatcher is a global pub or a sub handler that broadcasts payloads to registered callbacks. Dispatcher can easily manage dependencies between stores. This is not similar to generic pub-sub systems mainly because:

1. Callbacks are not subscribed to particular events. Each payload will be dispatched to each registered callback.

2. It is possible to defer in whole or in part until all the other callbacks have been executed.

Each Store registers a callback with the Dispatcher. When new data is entered, these callbacks would be utilized to send the data to the Stores. This process of invoking the callbacks is done through the dispatch() method. The function of dispatch() method is to provide a simple, synchronous iteration through the callbacks, through turn by turn invoking. As the complexities of applications increase, the dependencies across different stores will definitely take place.

It means, for example, when Store B updates itself, automatically we need a Dispatcher to invoke the callback for Store C. The wait functionality is done via the waitFor() method.

Here are APIs for Dispatcher functioning:

register(function callback): string Registers a callback to be invoked with every dispatched payload. Comes up with token to be used withwaitFor().

unregister(string id): void When the requirement is to remove a callback (based on the token)

waitFor(array<string> ids): void The store would wait for callbacks before continuing execution of the current callback. This is done only in response to a dispatched payload.

waitFor() gives a new iteration cycle over the dependencies. When all the dependencies are met, the original callback initiates. The waitFor() method can be used for various actions, for example when Store A is waiting for response from Store B. It is meant to wait for a specific action.

dispatch(object payload): void Dispatches a payload to all registered callbacks.

isDispatching(): boolean Is this Dispatcher currently dispatching.

The following example will give you a better understanding of how Dispatcher works. Consider a hypothetical situation of a flight destination form where a default city is selected when a country is selected.

var flightDispatcher = new Dispatcher();
// Keeps track of which country is selected
var CountryStore = {country: nullhttps://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png;
// Keeps track of which city is selected
var CityStore = {city: nullhttps://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png;
// Keeps track of the base flight price of the selected city
var FlightPriceStore = {price: nullhttps://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png;

When a user changes the selected city, the payload is

dispatched.flightDispatcher.dispatch({
actionType: 'city-update',
selectedCity: 'amsterdam'
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

This payload is digested by CityStore

flightDispatcher.register(function(payload) {
if (payload.actionType === 'city-update') {
CityStore.city = payload.selectedCity;
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

Now, when the user selects a country, the payload is

dispatched:flightDispatcher.dispatch({
actionType: 'country-update',
selectedCountry: 'brazil'
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

This payload is digested by both stores:

CountryStore.dispatchToken = flightDispatcher.register(function(payload) {
if (payload.actionType === 'country-update') {
CountryStore.country = payload.selectedCountry;
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

When the callback to update CountryStore is registered, a reference is saved to the returned token. Using this token with waitFor(), the CountryStore is updated before the callback that updates CityStore needs to query its:

data.CityStore.dispatchToken = flightDispatcher.register(function(payload) {
if (payload.actionType === 'country-update') {
// `CountryStore.country` may not be updated.
flightDispatcher.waitFor([CountryStore.dispatchToken]);
// `CountryStore.country` is now guaranteed to be updated.
// Select the default city for the new country
CityStore.city = getDefaultCityForCountry(CountryStore.country);
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

The usage of waitFor() can be chained like

this:FlightPriceStore.dispatchToken = flightDispatcher.register(function(payload) {
switch (payload.actionType) {
case 'country-update':
case 'city-update':
flightDispatcher.waitFor([CityStore.dispatchToken]);
FlightPriceStore.price = getFlightPriceStore(CountryStore.country, CityStore.city);
break; https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png);

The country-update payload will be guaranteed to invoke the stores' registered callbacks in order: CountryStore, CityStore, then FlightPriceStore.

Credits: Facebook Code

A Quick Overview of Flux Utils

In order to work with Flux, you need to have a solid foundation. This is provided through certain basic utility classes. Flux Utils provides those. However, they are not entirely a feature-complete framework, and they may not be able to handle all use cases.

It is possible to rely on other great Flux frameworks if the existing utilities do not address your case. Keeping that in mind, you can check out these main classes.

Store

ReduceStore

Container

In order to import these base classes from flux/utils, follow this code:

import {ReduceStorehttps://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png from 'flux/utils';
class CounterStore extends ReduceStore {
getInitialState(): number {
return 0;
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
reduce(state: number, action: Object): number {
switch (action.type) {
case 'increment':
return state + 1;
case 'square':
return state * state;
default:
return state;
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png
https://www.cabotsolutions.com/public/mobile-app-development-best-practices-cta.png

Credits: Facebook Code

Here are the best practices that needs to be followed when using these classes.

Stores - The function is to cache data. As they never have public setters they expose public getters to access data. It is also the function of the store to respond to the actions sent by the Dispatcher. The stores always change when data changes. They emit changes only during a dispatch.

Actions - Here, the Actions mean describing user actions, and not setter�s actions; for example, select-pageand not set-page-id

Containers - They are React components that control View. Their primary function is to gather the information from the store and save it. Containers do not have props or UI logic.

Views - They are also React components, but they are controlled by Containers. They have UI and rendering logic.

Popular Implementations of Flux

Now that you have got an overall idea of the Flux architecture, let�s take a look at few of the famous Flux implementations.

Redux - According to Github, Redux is a predictable state container for JavaScript apps. Many of the concepts are similar to functional programming, and all the data is kept in a single store.

Irrespective of the application size, Redux is always a single object, quite unlike Flux, which keeps separate stores for different kinds of data. If there are manipulations to be made on the data, it doesn�t affect the state. In this way, the state is immutable.

All updates and manipulation are done on a state tree. But this does not make the application slow as the data can be shared along several versions of the state tree.The updates on the application state is done through Actions, which are plain objects themselves, but contains a property depicting the kind of action performed. The data that describes the action will also be included.

The Store�s Dispatcher will dispatch the action and from there, it goes to the Reducer, and then to the current state tree. Here, the actions of the application would be described - the different things the application can do. Just a single reducer would be enough for the state transformation and action.

Reflux - It is one of the most popular implementations of Flux. But there are some basic differences between the two. Reflux doesn�t use a Dispatcher; instead each Action is a Dispatcher.As the Actions themselves are functions, there are no action creators. And the best thing about Reflux is that it is more concise and streamlined, with absolutely very less requirement of repetitive codes.

Fluxxor - Fluxxor makes use of a number of tools and Flux architecture to build JS data layers. In order to enjoy the full functionality of Fluxxor, you will have to make it work with React as the view layer.

Flummox - Flummox has three components, namely, Actions, Stores and Flux. In Flummox, you create some Actions, then create a Store that is responsive to those Actions.

In the next stage, you bring them together in Flux and use it in a View. Each of the Flummox components is represented by a class, and you extend from this base class.

Alt - Modeled after Flux, Alt is a library that facilitates the managing of state in JavaScript applications. You can install Alt, if you are installing package manager like nom or bower. Alt gives you the benefit of Flux, but with a better syntax.

Wrap Up

The main idea behind using Flux architecture is to have a simple application architecture. This makes it easier to maintain and reason about when it gets more complex. As there are no ambiguities on the relationship between various components, work gets moving.

On top of that, Flux is consistent and repeatable, making it very logical to work with, while creating an Action. It is also easier when you want the Store to know how to handle the Action, store data and activate change event.

You can rest assured that if Facebook is using Flux for production code, then it will definitely work for your project.Want to adopt Flux architecture for your next app development project? Don't hesitate to reach out to us; we can get you started.

Contact Us Today!

Mobile App Development Best Practices

Our Industry Experience

volunteer_activism

Healthcare

shopping_cart

Ecommerce

attach_money

Fintech

houseboat

Travel and Tourism

fingerprint

Security

directions_car

Automobile

bar_chart

Stocks and Insurance

flatware

Restaurant