Play Podcast

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 Reacts 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 applications business logic and other data. It updates all the Views.It works best with Reacts    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 setters 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, lets 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 doesnt 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 Stores 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