React: The UI Paintbrush You’ve Been Searching For

Introducing the first intuitive front-end web framework.

Afika Nyati
13 min readAug 25, 2017

As a graduating senior in high school, when probed by my elders and peers about my professional goals and plans for the future, my response always elicited confused reactions. Many people would not associate a Computer Science career with a student who, until then, had flourished in the fields of Visual Art and Music. Their reactions came as no surprise to me. Although I excelled in the sciences, many saw my foray into the engineering field as a waste of my other talents; I mean, isn’t engineering the antithesis of the arts? Since then, I’ve come up with many explanations that have justified my decision, but I think the following quote best explains my decision:

Creating things with your hands, or creating code, creating programs, are just different ways to express creativity.

- Elena Silenok (Founder, Clothia)

To me, painting, composing, and programming are all analogous, however they differ in tools and medium. In painting, you make use of paintbrushes (your tools) to apply paint (your medium) to a blank canvas (your product), while programming makes use of programming languages/frameworks (your tools) to write programs (your product) using code (your medium). However, in both cases, one creates something beautifully complex out of simple, elementary tools. Three years have elapsed since then, and in that time I’ve picked up a few skills from the world of computer science — especially in the realm of web development. However, up until this point, I had had difficulty finding the right paintbrush necessary for building user interfaces. Nothing I’d come across was clean, intuitive, or fun to use.

As a beginner programmer, my front-end stack comprised of CSS (Cascading Style Sheets) and jQuery (a JavaScript library that makes DOM manipulation easier for developers). With these technologies, I soon noticed that there was a very low scope with which I could create rich applications and user experiences. Overwhelmed by the plethora or frameworks out there, a friend recommended I try out the MEAN stack, an open source software stack used to build dynamic websites and web applications. In simpler terms, the MEAN stack makes use of four technologies to build web applications: MongoDB (a NoSQL database), Express.js (a web application framework that runs on Node.js), and Node.js (an execution environment for event-driven server-side and networking applications) for server-side concerns, and Angular.js (a JavaScript MVC framework that runs in browser JavaScript engines) for client-side concerns.

As “state-of-the-art” as I found this programming paradigm, I was not particularly wooed by it’s complexity — complexity that made it non-intuitive to the intermediate developer. With a focus on the front-end programming, I found Angular extremely difficult to grasp. Getting from one’s wireframes to a working user interface was quite the ordeal, only intensified by the fact that one’s Photoshop layers didn’t directly map to HTML elements. The following quote best describes my issues with Angular:

With Angular 1, it felt like the rabbit hole always went deeper. The more I learned, the more there was to learn. Compiling elements by hand, intercepting the digest cycle, and learning all these Angular internals…

- David Ceddia

Here’s a depiction of the general learning cycle associated with Angular:

Only in my case, I never reached the “OMG That’s Awesome!” plateau. Doomed by my friends ill-choice in stack technologies, I looked for better alternatives. To my fortune, I came across Meteor.js earlier in 2016. Meteor.js takes what MEAN Stack initiated and develops it further by integrating server-side and client-side code into a “do-it-all” environment. It came as a breath of fresh air to me but, even so, it still didn’t quite quell the key issues I had with the MEAN Stack, and it’s “do-it-all” wasn’t compatible with today’s front-end/back-end separation of concerns. Accepting that this was the best framework on the market, I saw it as the best framework for Tekuma’s technology platform. That was until I came across React.js

React is the front-end framework designers have longed for. Except it’s not really a framework. React’s website describes it like this:

React is a JavaScript library for creating user interfaces. Many people choose to think of React as the V in the MVC [Model-View-Controller]. We built React to solve one problem: building large applications with data that changes over time.

- React.JS Team

It’s developers, Facebook and Instagram, describe it as a library not a framework because, out of the box, frameworks like Angular offer a lot more functionality in comparison to React. However because of the React’s large open-source community, it’s easy to find a component for almost any functionality your heart desires. This in itself is a benefit, because it abstracts away the complicated details of implementing commonly expected functionality such as “Drag and Drop” or Routing that would otherwise halt consistent development for a beginner developer.

React’s spin on UI design doesn’t end there — there are many significant differences React benefits from, which many other front-end technologies lack. Some of these innovations have been so successful that competing frameworks have begun to take a page out of React’s book. In no particular order, I have outlined the features that set React apart.

The JSX Syntax

In order for developers to bring the reactivity and richness consumers have become accustomed to through native mobile applications to the web, they’ve had to integrate the DOM with one or more programming languages. This is the identifying quality of most powerful frameworks. If you’ve been paying attention, I’m sure you’ve noticed that I’ve mentioned this DOM concept twice so far, and I’m sure you’re itching for an elaboration. For the sake of keeping all readers in the loop, let me make a quick detour. Wikipedia describes the DOM as follows:

The Document Object Model (DOM) is a cross-platform and language-independent application programming interface that treats an HTML, XHTML, or XML document as a tree structure where each node is an object representing a part of the document. The objects can be manipulated programmatically and any visible changes occurring as a result may then be reflected in the display of the document.

Briefly, HTML is used to mark-up web pages. If a website were a house, HTML would be its foundation. Now that we’ve got that out way, let’s return to the idea of marrying HTML with a programming language. Most frameworks don’t necessarily use the same programming language. Over the last couple of years however, we have seen a proliferation of frameworks written in JavaScript, which as a result has become the de facto language of the web. Because HTML and JavaScript developed independently, most frameworks have found different ways to marry the two. One of those ways is by incorporating JavaScript into HTML markup. This is the method favored by Angular.js. There are problems to this method, though, which are best explained by the following extract:

…the stuff Angular understands in its HTML is not quite real JS. It’s a subset. And that abstraction is leaky. It works great, until it doesn’t. You end up second-guessing the code you’re typing into those strings. On top of the JS-like syntax, there’s the stuff that isn’t JS at all. Angular 1 had things like ng-repeat="items in items" and ng-click="doStuff()". Angular 2 switched it up a bit because people found the Angular directives confusing, so now it’s ngFor="let items in items".

- David Ceddia

Not fun. Consequently, the developers of React decided to take the complete opposite route by bringing HTML to JavaScript, and they’ve benefited greatly from their astute choice. They’ve done this by creating a syntax called JSX, which looks like XML mixed with regular JavaScript code. This method of integration is convenient because it allows developers to define those tree structures inherent to the DOM within their JavaScript code. As a result, your HTML markup is able to leverage the power of JavaScript, giving you more flexibility and control. In addition, for developers conversant with functional programming concepts, the use of the map, filter, reduce methods within the syntax to manipulate data sets seems almost intuitive. Below is an example of the JSX syntax:

Components

The reason I believe React is the perfect paintbrush for UI design boils down to this feature of the library. In React, developers are encouraged to break up their code into small, manageable, reusable fragments called components. This practice is crucial because:

  • From a programming standpoint, having many smaller components that build up to form one’s UI makes it much easier to maintain one’s code through modularity.
  • It helps one debug their application, test their application incrementally, and reason about one’s code.
  • It abstracts away the details of a given UI element, giving developers the ability to create their own components that one can later reuse, combine, nest, and share to their heart’s content, and in the process keep with the DRY (Don’t Repeat Yourself) principle.
  • Components and their behaviors are independent and remain encapsulated.
  • By breaking down your application — and the DOM — into smaller components, it becomes easer to imagine building a complex application.
  • From a design standpoint, developers can build their User Interface component by component, similar to how it would be done in any Adobe Creative Suite application. Layers in Photoshop are now directly mappable to fragments of code.

State, Data-Binding, and the React Lifecycle

This is probably my favorite React concept. React is declarative of how it handles state. The developers of React have miraculously made a “hard-to-grapple” concept, such as state, very intuitive and easy to understand. Part of the reason this is even possible is because they decided to implement a simple data model and flow. Where most frameworks choose to employ a two-way data binding model (hi Angular), React has opted for a one-way data binding model. To illustrate the differences between the two, I will have to briefly elaborate on the MVC (Model-View-Controller) pattern.

At heart, the MVC is a pattern employed by most GUI (Graphic User Interface) programs as a method to separate the concerns of the application. It separates the user interface (front-end) from the application (back-end), by putting the back-end code into the model and the front-end code into the view and controller. The model is responsible for maintaining application-specific data and providing access to that data, while the view queries the model for data in order to update the user interface to reflect the state of the most recent data.

In an application that employs a two-way binding model, a change to the view is able to mutate the model data, and visa versa. In an application with one-way binding, such as React, this can only be done in one direction. In the case of React, this is via the view mutating the model (or state).

This brings us to how react treats state. State is component-specific, meaning that a given component’s state is packaged along with its rendering function and methods. While, theoretically, all components in React could hold state, this is not the case — one of React’s best practices is to keep as many components as possible stateless, and isolate state into as few places as possible. This is done to minimize complexity and keep your application as clean as possible. This is the reason why one is able to comfortably reuse, combine, nest, and share components without the fear of bugs.

“But how do you know which components should have state and which should be stateless?” Generally speaking, your app state will correspond to your UI structure. I know that sounds rather vague, but in practice, the decision becomes reasonably intuitive. “But what if a given component’s behavior relies on the state of another component?” React deals with this by allowing components to share state through immutable properties called Props (passed properties). If you imagine your application as a tree structure, components higher in the tree (parent components) can pass down their state variables and methods to child components. However, the reverse is not true due to React’s unidirectional data flow. As a result, data is passed down and events are triggered up through event handlers.

Imagine a simple application containing a light bulb and a light switch. Ideally, the light bulb and switch would be two separate, stateless child components contained within a parent component with state. The parent component would keep track of the state of the switch (this.state.switchPressed), i.e. whether it is pressed or not. This state would be passed down to both child elements as props — the light switch would, in addition to the state, receive a toggle method (this.toggleSwitch) to mutate the value of the App state variable when the switch is clicked. This method would be tied to the switch as an event handler and respond to any click events on the light switch. As a result, when a user clicks the switch (an event), the this.props.toggleSwitch() method would be called by the event handler. This is an example of events triggering up the application. The method would then be invoked, toggling the switch state from “off” (false) to “on” (true), which in turn would be passed down to both child elements. The lightbulb would act on this new state by automatically re-rendering to the “light on” state, while the switch would act by automatically re-rendering to the “pressed in” state. In this way, information can be passed back-and-forth between components.

You can imagine how this concept might scale into larger applications. It’s important to remember that props are immutable (read-only), and cannot be re-assigned values. They can only be changed by invoking prop methods passed down from the parent element which, in turn, should call a special function called this.setState()within them to mutate the state variable tied to the props variable in question. In my opinion, this is a very simple and intuitive way of handling state.

These concepts are taken further by special methods called React Lifecycle methods. These methods are characteristic to all React components and allow us to hook into the views when specific conditions occur (e.g. when the component first renders or when the component is updated with new data). There are many lifecycle methods, but the most important ones are the invoked when a component is mounted/unmounted to the DOM, and when it receives new data.

Mounting/Unmounting

These lifecycle methods are invoked only once during the life of a component and are generally used to establish default props in our components, make Ajax requests to fetch needed data, or set up/remove any listeners. The methods in question are:

  • componentWillMount
  • componentDidMount
  • componentWillUnmount

The first two methods run when the component is initially rendered, but there is a subtle difference between the two: componentWillMount is invoked when the component is first invoked, while componentDidMount is only invoked when its children components have been successfully rendered. Therefore, if a child element fails to render, the component will fail to call this method.

New Data

These lifecycle methods are invoked whenever a component receives new data from its parent component:

  • componentWillReceiveProps
  • shouldComponentUpdate

The first method is used when you want to execute code whenever your component receives new props, while the second method is used only for advanced optimization purposes. By default, this method will always run causing a re-render to occur. However, if you have an intimate understanding of when your application needs to re-render, you can use this method to prevent it from re-rendering in all other cases where it doesn’t need to re-render. As a result, this improves the apps performance.

While I’ve only touched on five of the lifecycle methods, the diagram below highlights the entire React lifecycle chain:

That’s a mouthful! Before beginning this article, I thought I’d have an easy time describing the “ins-and-outs” of React in a succinct and easy-to-understand manner, but I’ve come to realize that there are many intricacies surrounding these features. I think it’s best to look at this article as an introduction to a “framework” that’s changing the way we view UI design on the web. If I’ve enticed your appetite, I encourage you to seek out more information about React. I can assure you, React and its ecosystem have many more treats in store (shout out to Babel, ES6, and arrow functions). As a student birthed by the arts and groomed by the sciences, I can confidently say that React is a sweet marriage of the two worlds, and it’s because of this that I implore you to try it for yourself! Once you’ve picked it up, I guarantee you won’t have any more issues painting future UI’s.

The fact that you can open up any JavaScript file with a React component in it and understand all the possible states of that component and exactly how it’s going to behave just by looking at the file, is incredibly powerful.

- Tom Occhino, React.js Conference 2015 Keynote

--

--

Afika Nyati

Design Technologist | Human-Computer Interaction | Artist | Composer | MIT ‘18