Achieving Business Goals with the Nuclear Energy of React.js

18 Jul 2016

 

The world-wide web has become very dynamic and complex. A myriad of UI elements should interact with one another while being responsive to the user. For example, if the user presses the button “A”, the button “B” should be hidden, but several additional panels with their own buttons, checkboxes, and other UI elements should be shown. If a developer is trying to implement this functionality in a typical JS-imperative paradigm, it turns into “callback hell.” After some time, technical debt makes support of such an application and development of new features virtually impossible.

Present-day frameworks, such as Angular, may seem like a solution, but they create substantial “accidental complexity” in the framework. At first, dynamic, asynchronous pages may look fine simply because they work. However, as the project becomes more complicated, we become trapped in the framework.

When using a certain framework, we can only work within its parameters, and we cannot leave it. Like taking a subway, once you go through the stile, you have to take whatever routes are available until you get to your destination. Yes, we can take a shovel and start digging “on the side,” trying to “patch” and “hack” the framework, but this is very difficult. We can travel between stations fast enough, but our routes remain limited.

In my opinion, React.js ranks third in the top milestones of modern web architecture, right after AJAX and jQuery. AJAX enabled web pages to become dynamic and asynchronous. jQuery also alleviated this process, allowing the UI to be more easily manipulated. React allows the pragmatic creation and manipulation of complex, technically sound UI even more effectively.

React is not only a new JS library; it is a new idea in web development. It has a more functional and declarative approach than JavaScript and other popular frameworks, which complies with computer science principles. Moreover, it can be integrated into your current development process quite easily.

React also has a very simple, compact API.  This means developers can transition to React just by drawing from their JavaScript and functional programming skills.  Other complex, modern frameworks, like Angular.js and Ember.js, require very specific knowledge. In contrast, React has a very low learning curve.

When using React, we no longer have to worry about every previous phase of UI, and previous phases do not affect the next phase. We do not have to manipulate the DOM directly. We can just change the data and immediately see its projection.

This simplicity eliminates headaches associated with synchronization of data and its display in the UI. No more “accidental complexity” within the framework and implementation. Only the natural complexity of the business objectives and features remains. With React, developers can engage in business concerns instead of fighting with tools like Angular.

Working with React sounds good, but how does it look? To illustrate its functionality, I created the coffee-shaped pseudo-code below for “some button” component. Actually, React works well with any front-end language, especially with ClojureScript.

Example of simple button component:

SomeButton = (target, name) ->
 <a href={ target } className="btn"> { name } </a>

Now we can use this component anywhere in the application:

<SomeButton target="/about" name="About us" />

This looks compact and clear, doesn’t it?

I intentionally omitted some syntax details to better convey the essence. Although React uses the concept of “classes,” I recommend using components as functions. They actually work more like functions. The concept of “classes” is used to obtain some OOP functionality with mixins, inheritance, and own state in the components.

Here is a complete description of our “some button”:

SomeButton = React.createClass
 render: ->
	<a href={ @props.target } className="btn"> { @props.name } </a>

As you can see, only one necessary component element called “render” is present. This is a function assigned to the component that visualizes the data. At this moment, it is just a button. We can also use other methods of API React to manage the life-cycle of a component, including componentWillMount, componentDidMount and others.

We can also see the combination of HTML and JS. This can be confusing. We have always tried to carefully separate logic from presentation, and this “new technology” wants us to mix them? Yes, and this makes sense. This approach allows us to create a more simple and declarative representation of UI.

I will now use simplified pseudo-code to show a more interesting example.

What if we want to create a user panel? The code would look like this:

UserPanel ->
    if user.signed_in?
        <Avatar photo={ user.photo }/>
        <span> { user.name } </span>
    else
       <Button onClick="signInModal"> Sign in </Button>

Now we can place  <UserPanel /> anywhere, and the component will decide how it should look in accordance with the current state of the application. Should a profile picture and username be shown? Or a login button? The component itself will determine this for us.

What if we want to create code related to ecommerce?  First we should implement a couple important components, like “product” and “product list,” as in this example:

Product ->
    <div>
        <img src={ product.image } />
        <span> { product.name } </span>
        <BuyButton product />
    </div>

ProductList ->
    getProductsFromServer()
    for product in products
        <Product product />

This process is similar to building structures with Lego blocks. We simply create complex components from simple ones. But what lies behind this process? Every time we change data, React redraws the entire UI completely. Like a mirror, it reflects all data changes. We do not have to take any extra steps or double-check that the correct data is displayed on the page. This is normal for any functional paradigm.

The secret of React’s superior performance lies in its optimizations, one of which being “Shadow DOM.” Carrying out operations with the real DOM are quite costly, but React’s optimizations eliminate this need. First, React recreates all components within a virtual “Shadow DOM.” Then, it compares the shadow with the real DOM and replaces only those parts that have changed.

The rendering looks fine, but what about the architecture?

Facebook offers its own solution: FLUX. FLUX contains four entities:

  1. Components – Described above.
  2. Actions – Manipulates the state and communicates with the server and external world.
  3. Dispatcher – Routes data to the “stores” (at times a superfluous detail).
  4. Stores – Functions as an application state warehouse.

All this activity works in only one direction: components -> actions -> dispatcher -> stores -> and back to components again in a continuous loop.

  1. The user sees UI (Components) and interacts with them. An interaction (clicks, text input, swipe) implements Actions.
  1. Actions sends and receives data from the server and creates messages for Dispatcher.
  1. Dispatcher receives the message from Actions and places data in the appropriate Stores.
  1. Components react to changes in Stores, and re-render UI.

This process occurs in this direction only. No more two-way bindings. This approach allows us to more easily troubleshoot and/or add new functionality into the application at any given time.

It’s simple, but not simple enough. I now want to offer a much simpler version of stores: Baobab.js.

Baobab is a very smart store, inspired by ClojureScript library Om. It combines the store and the dispatcher in one package.

The architecture of our application will become even simpler with Baobab. Now we have only three steps:

components -> actions -> Baobab store ->  components (loop continues)

Now let’s imagine a simple case involving a list of employees.

The user sets the age range of 28-32 in a special form on the page with a list of employees displayed by the component StaffList. Using the above architecture, the first step tells Actions, “getEmployees with parameters  { age: 28..32 }.” Actions sends a GET request to the server and waits for a response asynchronously (“promise pattern”). When the data is received, “promise” puts data into Baobab in a special branch called “employees.” Components immediately responds to changes, redraws the page, and the user can see the updated list.

React allows the creation of new features regularly and quickly, without lowering quality or losing supportability. It allows you to successfully achieve ambitious goals, comparable to using nuclear energy to launch a rocket ship. React will also enhance developers’ skills by teaching them a more efficient way to create and customize UI. Overall, it will result in a positive user experience because it is indeed reactive.