React, Babel and JSX

Learn how Babel compiles JSX to JS and how to create a React project from Scratch.

Using Babel for JSX

Like any other JavaScript library, React is fully usable through plain, ordinary JavaScript code. But hardly anyone uses it that way. Instead, they compile a language called JSX down to ordinary JavaScript.

JSX allows HTML-like markup to be embedded within JavaScript code. Every tag in JSX is converted to a call to React.createElement(). For example, consider the following code:

const helloJSX = <h1 className="super-big">Hello, JSX!</h1>;

This code would be compiled to:

const helloJSX = React.createElement(
  'h1',
  { className: 'super-big' },
  'Hello, JSX!'
);

If you’re new to JSX, this new syntax will take some getting used to. But it makes code much easier to read and write than the equivalent series of React.createElement() calls would be. For more details on JSX syntax, take a look at the React docs.

The compiler that translates JSX into ordinary JavaScript is known as Babel. And it does so much more than just JSX: with Babel, you can write code that uses JavaScript features that are only implemented in leading-edge browsers and run that code everywhere. More precisely, you can run that code in any JavaScript environment that supports the ECMAScript 5 standard (2009). Remember Internet Explorer 9? Thanks to Babel, it can run React code.

An Ode to CoffeeScript

CoffeeScript was a language introduced by Jeremy Ashkenas in 2009 as “a little language that compiles into JavaScript.” CoffeeScript was hugely influential in two respects:

  • It pioneered a number of syntax features that would make their way into the ECMAScript 6 standard.
  • It was the first compile-to-JavaScript language to catch on. The success of CoffeeScript sparked widespread interest in ES6-to-ES5 compilers, which is how Babel came to be.

CoffeeScript’s time has passed, but today’s JavaScripters may have it to thank for kicking off an era of innovation for the once stagnant language.

To start using Babel, add its core package to the project:

$ npm install --save-dev @babel/core@7.2.0
+ @babel/core@7.2.0

As with ESLint, Babel requires some configuration to make it useful. For this project, you’ll start with two popular Babel presets:

  • The React preset, which provides support for JSX.
  • The env preset, which provides support for all new JavaScript syntax features defined in ES2015 (a.k.a. ES6), ES2016, and ES2017. The name “env” refers to its ability to tailor the transpilation pipeline to a specified set of target environments.

Steps to incorporate Babel with React

Following are the steps to incorporate Babel with React:

  • Install the presets with npm:

    $ npm install --save-dev @babel/preset-react@7.0.0 @babel/preset-env@7.2.0
    + @babel/preset-react@7.0.0
    + @babel/preset-env@7.2.0
    
  • Then bring in the two presets from a new file called .babelrc.js:

    // .babelrc.js
    module.exports = {
      presets: ['@babel/preset-react', '@babel/preset-env'],
    };
    
  • Babel will now apply this configuration to every JS file in the project. To try it out, create a JS file called hello-babel.js:

    // hello-babel.js
    import figlet from 'figlet';
    console.log(figlet.textSync('Hello, Babel!'));
    

    This file uses the syntax of the ES2015 module in the form of the import keyword. If you try running it in Node without Babel, you’ll get a syntax error:

    $ node hello-babel.js
    /Users/tburnham/code/test-driven-carousel/hello-babel.js:1
    (function (exports, require, module, __filename, __dirname) {
        import figlet from 'figlet';
      ^^^^^^
    
    SyntaxError: Unexpected token import
        at createScript (vm.js:80:10)
        at Object.runInThisContext (vm.js:139:10)
        at Module._compile (module.js:616:28)
        at Object.Module._extensions..js (module.js:663:10)
        at Module.load (module.js:565:32)
        at tryModuleLoad (module.js:505:12)
        at Function.Module._load (module.js:497:3)
        at Function.Module.runMain (module.js:693:10)
        at startup (bootstrap_node.js:191:16)
        at bootstrap_node.js:612:3
    
  • To run this file through Babel from the command line, you will need the @babel/cli package:

    $ npm install @babel/cli@7.2.0
    + @babel/cli@7.2.0
    

    @babel/cli includes an executable called babel that you can run with npx:

    $ npx babel hello-babel.js
    "use strict";
    
    var _figlet = _interopRequireDefault(require("figlet"));
    
    function _interopRequireDefault(obj) {
      return obj && obj.__esModule ? obj : { default: obj };
    }
    
    console.log(_figlet.default.textSync('Hello, Babel!'));
    

    You don’t need to understand the details of this code. Long story short, Babel has compiled the import syntax into something that’s compatible with Node and other environments that don’t support ES2015 modules.

  • You can run the compiled script by piping it into node. But first, install the package it’s trying to import:

    $ npm install figlet@1.2.0
    + figlet@1.2.0
    

    Now check out what happens:

    $ npx babel hello-babel.js | node
      _   _      _ _          ____        _          _ _
     | | | | ___| | | ___    | __ )  __ _| |__   ___| | |
     | |_| |/ _ \ | |/ _ \   |  _ \ / _` | '_ \ / _ \ | |
     |  _  |  __/ | | (_) |  | |_) | (_| | |_) |  __/ |_|
     |_| |_|\___|_|_|\___( ) |____/ \__,_|_.__/ \___|_(_)
    

    Figlet took a plain old string and turned it into ASCII art. Pretty cool!

  • You can clean up hello-babel.js and its dependencies, as we won’t need them:

    $ rm hello-babel.js
    $ npm uninstall @babel/cli figlet
    

Then commit the new .babelrc.js and the changes to package.json:

:wrench: Initial Babel setup

In the next section, we’ll use the power of Babel to bring exciting new syntax features to the world of Jest testing.

Try to carry out steps to incorporate Babel with React below. All the files have been completed for you.

Get hands-on with 1200+ tech skills courses.