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.
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.
React.createElement(), doing this for an entire UI is very verbose. Often React elements are created in JSX, which uses an HTML style syntax.
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).
state are what allow components to be dynamic, living entities.
React.createElement("p", null, "Hi There!"). The same element is created in JSX with the following syntax:
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.
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
To hook up React with this HTML element the
render() function is called. The following code sample sets up the entire React application.
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 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.
render() function is called, the React application is successfully initialized. It is time to build the
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.
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.
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.
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.
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.