From native JavaScript to React

Understanding React from the ground up

By Stéphane Bégaudeau on October 1, 2018

React is a JavaScript framework for building user interfaces. It can be used to create JavaScript applications by dynamically manipulating page content. Browsers already provide an API for creating elements in a page, the DOM, so newbies might be wondering what React brings and how it relates to the DOM.

Native JavaScript and DOM

In JavaScript, as in most programming languages, you will have access to a global scope with various objects and functions that you can manipulate to build your application. In a JavaScript application running in a web environment, you will have access to the Document Object Model (DOM) API. If you’re using JavaScript in a node-based application, you won’t have access to the DOM, but you can import alternative implementations, such as JSDOM.

The DOM is a simple API that lets you manipulate a page’s HTML document in almost any way you want. You can start using it thanks to the global document object.

Starting from document here, you can easily create new elements, modify their properties, and even add them as children of other elements. Thanks to the DOM, you can programmatically create any HTML document, even if doing so would be very verbose.

In the following example, we will programmatically create a simple heading in an HTML document.

 <!DOCTYPE html>
<html>
  <head>
    <script src="app.js"></script>
  </head>
  <body>
    <div id="app" />
  </body>
</html>

To do this, we will create an h1 element that will be inserted into the body of the HTML page.

 // The document object is accessible since it is in the global scope
const h1Element = document.createElement('h1');
h1Element.setAttribute('class', 'title');
const textElement = document.createTextNode('I am Groot');
h1Element.appendChild(textElement);

// document.getElementById('app') will retrieve the div with the identifier app
document.getElementById('app').appendChild(element);

The above code first creates a new attribute and then adds a new attribute with class value title to the element h1. It also creates a simple text node and adds the text ‘I am Groot’ as a child of element h1. Finally, it uses the HTML document to add the h1 tag to the div. After the app executes this code, the resulting HTML document will look like this:

 <!DOCTYPE html>
<html>
  <head>
    <script src="app.js"></script>
  </head>
  <body>
    <div id="app">
      <h1 class="title">I am Groot</h1>
    </div>
  </body>
</html>

With the help of the DOM, we can also directly manipulate the class attribute of an element through the className attribute (since the name class is a reserved keyword in JavaScript). So the following code will produce the exact same result.

 const h1Element = document.createElement('h1');
// h1Element.setAttribute('class', 'title');
h1Element.className = 'title';
const textElement = document.createTextNode('I am Groot');
h1Element.appendChild(textElement);

document.getElementById('app').appendChild(element);

Basics of React

Most React tutorials will get you started by using all the wonders of React directly. We’ll take a different approach, as we’ll start by writing some React code that you’ll probably never write again to get a better understanding of how React works.

React was created with web scenarios in mind, so at its core, some of its APIs feel like the DOM. To illustrate this, we’ll take a look at one of the most important React APIs, React.createElement.

To manipulate the DOM with React, you will need two dependencies, React and ReactDOM. React.createElement will let you create a cheap and fast data structure, called a virtual DOM, that represents the structure of your user interface. ReactDOM will render this virtual DOM in your web application’s real DOM.

React.createElement will take three arguments to create the element of the virtual DOM:

  • the name of the element to create
  • its properties
  • its children
 import React from 'react';

const name = 'h1';
const props = { className: 'title' };
const children = 'I am Groot';
const element = React.createElement(name, props, children);

React.createElement can also accept an array containing all the child elements of the element to be created.

 import React from 'react';

const name = 'h1';
const props = { className: 'title' };
const children = ['I am Groot'];
const element = React.createElement(name, props, children);

The parameter children is also a regular property of the element, so it can be part of the props object.

 import React from 'react';

const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = React.createElement('h1', props);

In order to render this element in the DOM, we need to choose where it should be rendered in the DOM, in our case a div with the identifier app and tell ReactDOM to render it.

 import React from 'react';
import ReactDOM from 'react-dom';

const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = React.createElement('h1', ...props);

ReactDOM.render(element, document.getElementById('app'));

All code samples shown here can be tested by using them with unpackaged versions of React and Babel. Such configurations should only be used for simple tests, as they are not as optimized as production builds. In this specific case, the imports of and (both exposed here as global variables in react) should be removed. react-dom

 <!DOCTYPE html>
<html>
  <head>
    <title>React</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
    const props = {
      className: 'title',
      children: ['I am Groot']
    };
    const element = React.createElement('h1', props);

    ReactDOM.render(element, document.getElementById('app'));
    </script>
  </head>
  <body>
    <div id="app" />
  </body>
</html>

JSX that ordinary people can also learn

While we could use this method to create all the pages of a web application, it is still very verbose. To make manipulating the DOM easy, React provides a simple yet powerful language called JSX.

The preprocessor uses JSX to convert it to regular JavaScript during build time. A regular React project uses a preprocessor to convert JSX code to React.createElement. Therefore, JSX is never interpreted directly by React, and you can use React without a single line of JSX. Therefore, the two pieces of code below are exactly the same. First, use React programmatically:

 import React from 'react';

const props = { className: 'title' };
const children = ['I am Groot'];
const element = React.createElement('h1', props, children);

or using a JSX declaration:

 import React from 'react';

const element = <h1 className="title">I am Groot</h1>;

Since the JSX code will use the conversion to call React.createElement, you need to import React even though it doesn’t seem to be used.

With JSX, you can create most of the DOM declaratively very quickly, while React will only see calls to React.createElement. Since JSX elements just call React.createElement on them, children are still regular properties. So you can also write the previous example like this:

 import React from 'react';

const element = <h1 className="title" children="I am Groot"/>;

With JSX, you can access variables through curly braces:

 import React from 'react';
const title = 'title';
const text = 'I am Groot';

const element = <h1 className={title} children={text}/>;

Of course, we can also name the variable the property we want to manipulate

 import React from 'react';

const className = 'title';
const children = 'I am Groot';

const element = <h1 className={className} children={children}/>;

This will allow us to use the extended syntax for cleaner code

 import React from 'react';

const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = <h1 {...props}/>;

Finally, we can render this element in the DOM with React.createElement as before.

 import React from 'react';
import ReactDOM from 'react-dom';

const props = {
  className: 'title',
  children: ['I am Groot']
};

ReactDOM.render(<h1 {...props}/>, document.getElementById('app'));

Now that we’ve rendered our first piece of virtual DOM with React using JSX, we’re ready to see how to build a basic application with React.

Go ahead and develop more dynamic code with React components.