DISCOVERY

May 31st, 2018

React & Webpack Seed Project Part I: Building With React

React

JSX

JavaScript

ECMAScript 6

Webpack

Since mid March a lot of my free time work has been dedicated to building React.js apps. In fact, I built this website in the past month and a half with the MERN stack - MongoDB, Express, React and Node.js. Before I started building this website I built a sample prototype application using two key technologies - React and Webpack. The knowledge I learned from this prototype helped jump start my work on the website. This discovery looks at the first technology used in the prototype application - React. I will look at the Webpack portion of the prototype in my next discovery post.

React is a library for generating views. A view is the UI of an application, and for a web application it is rendered HTML. In a traditional web application, the client side JavaScript code manipulates the HTML view through the Document Object Model (DOM) API. When using React on the client side, views are interacted with through a construct called the "Virtual DOM."

Virtual DOM

The Virtual DOM is a layer of abstraction used over the Document Object Model (DOM) in React. The Virtual DOM is kept in memory and is altered using the React library. A React developer never interacts with the DOM API itself. They only communicate with the Virtual DOM to change the UI. Behind the scenes, React makes sure the Virtual DOM's virtual representation of the UI matches the state of the DOM1.

The biggest difference between the Virtual DOM and the DOM is that the Virtual DOM implements a declarative API while the DOM's API is imperative. In other words, one programmer tells the DOM API how the view needs to change while another programmer tells the Virtual DOM what needs to change about the view. Imperative is how something needs to be done to accomplish a task. Declarative is what task should be accomplished.

A more in depth analysis of imperative and declarative paradigms is beyond the scope of this discovery post, but in the context of the Virtual DOM a developer doesn't need to know how the DOM API works in order to update views. All a React developer needs to tell the Virtual DOM is what they want the view to be. React is declarative - it asks the developer for what needs to be accomplished and internally it takes care of how its done.

Reacts declarative approach makes it easy and quick to create views without the learning curve of the DOM API. However, the Virtual DOM does have some drawbacks. First off its memory intensive since the UI is kept in memory throughout the applications lifecycle2. With the DOM API you do not have this additional overhead. Also you don't have the expressiveness and speed of the DOM API with the Virtual DOM (A major misconception is that React is faster than the traditional DOM - this is false3,4). With the DOM API you know based on your code exactly how the DOM will respond, while with React you have to hope the Virtual DOM makes the correct choice for you.

Despite the drawbacks using a declarative approach makes creating views a breeze for JavaScript developers. React allows developers to think of view elements as a simple construct - the JavaScript object! Views in React are made up of many building blocks called React Elements.

React Element

A JavaScript object that represents the smallest building block of the UI. In a web environment a React element represents an HTML element (also referred to as a DOM node). It can also represent a React component. While a React element can be created directly as a JavaScript object with React.createElement(), doing this for an entire UI is very verbose. Often React elements are created in JSX, which uses an HTML style syntax.

React Component

Components in React are a form of encapsulation over React elements. Components promote code reuse, containing a piece of the UI that can be used multiple times throughout an application. Components also have lifecycles and can contain props (values passed to the component from other components) and state (data specific to the component instance). props and state are what allow components to be dynamic, living entities.

JSX

JSX is an extension of the JavaScript language created by Facebook for React. It follows HTML-like syntax to create hierarchies of React elements. For example, a React element in JavaScript is created like so: React.createElement("p", null, "Hi There!"). The same element is created in JSX with the following syntax: <p>Hi There!</p>

With these concepts in mind, let's go over the React seed project I built! Here is what the final product looks like:

The first step of a React application is to build an HTML template for React.js to latch onto.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>React.js Webpack Seed</title> </head> <body> <div id="react-container"></div> </body> </html>

This HTML document contains a body with a single div element. React will begin rendering further HTML elements dynamically inside this element.

You may be wondering where the <script> tag is for the JavaScript. Webpack actually handles bundling the JavaScript and including it in the HTML document, so we don't have to worry about it! I will discuss the Webpack aspects of this project in my next discovery post.

To hook up React with this HTML element the render() function is called. The following code sample sets up the entire React application.

import React from 'react'; import {render} from 'react-dom'; import App from './App'; window.React = React; render( <App />, document.getElementById('react-container') );

The render() function takes two parameters. The first is the React element that will be rendered - which in this case is a React component I created called App. The App component holds the UI and state for the entire application.

The second parameter is the container in which the React element is rendered. This is the only DOM API call made in the application. document.getElementById('react-container') finds the HTML element with the given id in the previously shown HTML file.

Once the render() function is called, the React application is successfully initialized. It is time to build the App component.

There are a couple of different ways to build a component in React. For the App component I used a class based approach. Later you will see the other two components in the application using a functional approach.

Why did I choose the class based approach over the functional one? A class based component has access to lifecycle methods and component state. On the other hand a functional component is stateless and only has one function - therefore there is no way to redefine the lifecycle methods.

Since the App component needs to hold the state of my entire application, I need to use a class based component. A class based component extends the React.Component class using ES6 class syntax.

class App extends React.Component { constructor(props) { super(props); this.state = { technologies: [ { id: "375e6c2b-d799-47ef-848d-84b42bef7a29", name: "JavaScript", picture: "./assets/js.png", release_date: moment('1995-12-04') }, { id: "75bb50f5-9067-4a30-964f-a3f0d42b5ca4", name: "Webpack", picture: "./assets/webpack.png", release_date: moment('2012-03-10') }, { id: "ed13c757-27cd-4cc1-b4ac-de449ee9cbae", name: "React", picture: "./assets/react.png", release_date: moment('2013-03-01') }, { id: "d9f08c13-f59f-45bb-b8e9-0bd0114b0adf", name: "Sass", picture: "./assets/sass.png", release_date: moment('2006-11-28') } ] } } render() { const {technologies} = this.state; return ( <div> <div className="title-container"> <p className="title">React Webpack Seed</p> </div> <p className="sub-title">Technologies used</p> <TechnologyList techList={technologies} /> </div> ); } }

The application displays a list of different technologies. In the code above these technologies are assigned to this.state. This variable holds the state for the component.

Another major piece of this component is the render() function. The return value of this function is what is rendered in the HTML. The returned value is a hierarchy of React Elements in the form of JSX. I also deconstructed the technologies array from the state and passed it as a prop to the TechnologyList component. Remember that props are simply values passed from one component to another. The TechnologyList component orchestrates the UI display for all the technologies. Let's look at that now.

import React from 'react'; import Technology from './Technology'; import PropTypes from 'prop-types'; const TechnologyList = ({ techList=[] }) => <div className="technology-list"> { (techList.length === 0) ? <p>No Data</p> : techList.map(technology => <Technology key={technology.id} {...technology} /> ) } </div>;
TechnologyList.propTypes = { techList: PropTypes.array }; export default TechnologyList;

Unlike the main application component which holds state, TechnologyList is a stateless functional component. Keeping only one component stateful makes an application easier to manage since no child components will cause unexpected changes to the application state.

An easy way to reason about stateless functional components is that the entire function is a render() function. Whatever the function returns will be rendered to HTML.

The functional component takes one parameter - the props passed to the component. I destructured the props in the function parameter definition itself. The syntax techList=[] defines a prop called techList with an empty array default value.

In the JSX for this component I incorporated some JavaScript code to check if the technology list is populated. Depending on whether or not its populated, different React elements are rendered. If there are objects in the list, a Technology component is rendered for each one. This shows the dynamic nature of React and JSX - depending on the state and props passed into a component different UIs are displayed.

Finally I defined the propTypes variable on the TechnologyList component. This is used for property validation. If a prop type is passed in to the component that doesn't match the type defined in propTypes, a warning is issued. This is extremely helpful for catching bugs early and unit testing5.

The last component displays information about the technology. It is a functional stateless component. You can use all the concepts I went over in this discovery post to understand what is happening here.

import React from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; const Technology = ({ name, release_date, picture }) => <div className="technology"> <figure> <img src={ require(`${picture}`) } /> </figure> <p className="tech-name">{name}</p> <p className="tech-release-date"> {moment(release_date).format('MMMM Do, YYYY')} </p> </div>; Technology.propTypes = { name: PropTypes.string.isRequired, release_date: PropTypes.instanceOf(Date).isRequired, picture: PropTypes.string.isRequired }; export default Technology;

That is all the JavaScript React code needed to create the UI for my seed project. I have enjoyed working in React so far. Using functional techniques and pure JavaScript to create modular front-end code definitely makes React stand out. I am still early on in the React discovery process, but considering I have a website in production written with the library I will continue to learn!

You can find all the code along with Sass styling & Jest unit testing on Github. Next time I will go over the Webpack portion of the project!

[1] "What is the Virtual DOM?", https://reactjs.org/docs/faq-internals.html#what-is-the-virtual-dom

[2] "React (JavaScript library)", https://en.wikipedia.org/wiki/React_(JavaScript_library)

[3] "Why Virtual DOM is slower", https://medium.com/@hayavuk/why-virtual-dom-is-slower-2d9b964b4c9e

[4] "Myth: React is 'faster than DOM'", https://twitter.com/dan_abramov/status/842329893044146176

[5] Alex Banks & Eve Porcello, Learning React (Beijing: O'Reilly, 2017), 109