{ JSX and Babel. }

Objectives

By the end of this chapter, you should be able to:

  • Understand what JSX is and how it is used with React
  • Define what a transpiler is and include babel-core in an application
  • Conditionally create JSX based on props

JSX Introduction

JSX allows you to write HTML in your JavaScript. Writing HTML in your JavaScript is a very different approach when comparing React to other frameworks and libraries. The benefit, however, is that we can write our HTML in a way that's familiar, rather than having to pull functions from React to generate DOM elements. Here is what a component using JSX looks like:

class App extends React.Component {
    render() {
      return (
        <div>
          <h1>Hello World!</h1>
        </div>
      );
    }
}

With JSX, we no longer have to use React.createElement or React.DOM to create common elements like divs and h1s. We can simply return the JSX that we want!

But there is an issue: JSX is not understood by the browser. Instead, we need to "convert" our JSX into JavaScript. To do the conversion, we need a little bit of help from a transpiler. You can read more about transpilers in this scotch.io article, but the main idea is that a transpiler will take our JSX code and convert it into code that uses React.createElement. Enter babel, a transpiling framework.

Babel: Getting Set Up

Text Editor Setup For Babel

Make sure that you have JSX syntax highlighting for your text editor, otherwise your React components will be difficult to read (JSX will not be highlighted). For example, in Sublime the package you should search for and install is simply called "Babel." Once it's installed, you can set the syntax of your JSX files to JavaScript (Babel) in order to get the proper highlighting. (More advanced configuration options can be found here.)

Simple Web Server For Babel

For our next code example, you won't be able to run the code if you open the HTML file in your browser through the file system! (If the URL in your browser bar starts with file://, the transpilation won't work.)

Instead, you must start an HTTP server to serve your code. One simple option for a server is SimpleHTTPServer, which is built in to Python. Open up your Terminal and navigate to the directory where your HTML file is. Then type

python -m SimpleHTTPServer 8000

Next, open up your browser and go to http://localhost:8000. From there, you should be able to navigate to your HTML file. Once you have a web server running, you can move on to the babel examples. If you're a little uncomfortable with the Terminal, make sure to check out our free Terminal and UNIX Course!

Babel

In order to convert our JSX to JavaScript, we need to transpile our code. The tool we will use to transpile will be babel. To include babel, we can add the following script tag:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.js"></script>

In order to alert the browser that we want babel to transpile our code, we also need to modify the type on any script tag linking to jsx code that we write. Specifically, we need to set type to have a value of text/babel. In the following example, notice that the app.jsx script has the text/babel type:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" href="app.css">
  <title>React + Babel</title>
</head>
<body>
  <div id="app"></div>
  <script src="https://unpkg.com/[email protected]/dist/react.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.js"></script>
  <script type="text/babel" src="app.jsx"></script>
</body>
</html>

Let's use JSX in a component. In your app.jsx, try writing the following:

class App extends React.Component {
  render() {
    return (
       <div>
         <h1>Hello JSX and the World!</h1>
       </div>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('app')
);

You can see this on CodePen here

This code sample creates a component that has a div and inside of the div an h1 tag with our text. But what if we want to pass in a prop to our component? How do we use those props in our JSX?

In the next example, we will pass in a prop to the component and display the text from the prop in our h1:

class App extends React.Component {
  render() {
    return (
       <div>
         <h1>Hello {this.props.name}!</h1>
       </div>
    );
  }
}

ReactDOM.render(
    <App name="student"/>,
    document.getElementById('app')
);

As you can see from the above example, if we want to use the value of this.props.name in the JSX, then we must wrap it in curly braces. In fact, any code wrapped in curly braces will evaluate JavaScript. this.props.name is simply a JavaScript variable that we are looking up inside of the curly braces. Here is another example in which we give our h1 tag some styling and also comment out some code we're not using:

class App extends React.Component {
  render() {
    var style = {color: "red"};
    return (
       <div>
         <h1 style={style}>Hello {this.props.name}!</h1>
         {/* <p>
            This JSX will not be rendered because it is commented out using JavaScript
         </p> */}
       </div>
    );
  }
}

ReactDOM.render(
    <App name="student"/>,
    document.getElementById('app')
);

Notice that the p tag is commented out because it is wrapped is a JavaScript comment using the curly braces. Another interesting thing to point out here is that we are using a JavaScript object to create a style for our h1 tag. Because the style variable is a JavaScript object, we must be sure to put the red value in quotes.

Adding CSS Classes to JSX

Let's say we want to add some CSS to a file called app.css. Adding a CSS class to your JSX is also possible. Add the following CSS to the app.css file:

.primary-text {
   color: blue;
   font-size: 2em;
}

If we want to add the primary-text class to an element in our component, we may be tempted to write the JSX like this:

<p class="primary-text">This should be large blue text</p>

However, as we mentioned earlier, when adding classes to a React component, you have to use the className attribute to specify a CSS class rather than using the class keyword. The full example looks like this:

class App extends React.Component {
  render() {
    var style = {color: 'red'};
    return (
      <div>
        <h1 style={style}>Hello {this.props.name}!</h1>
        <p className="primary-text">This should be large blue text</p>
      </div>
    );
  }
}

ReactDOM.render(
    <App name="student"/>,
    document.getElementById('app')
);

You can see what this looks like on CodePen here

Conditional JSX

Very commonly we want to add conditional logic to our JSX. One common way to conditionally produce the JSX we want is to put our conditional logic above our return statement. Additionally, since we have the full power of JavaScript inside of JSX, we can add ternary logic to the JSX. Here's an example:

class App extends React.Component {
  render() {
    var name = this.props.name;
    if(name === "Tim"){
      name = "favorite instructor"
    } else if (name === "Matt" || name === "Elie") {
      name = "very solid instructor"
    }
    return (
      <div>
          <p>{this.props.name}</p>
          <p>{name}</p>
          {name === "student" ?
              <h1>Good job on the course so far!</h1>
              :
              <h1>Hello, {name}!</h1>
          }
      </div>
    );
  }
}

ReactDOM.render(
    <App name="Moxie"/>,
    document.getElementById('app')
)

There's a lot of conditional logic going on in the example above; try to guess what will render on the page before opening it up. At the bottom, try changing the value you pass in to name to some other value. How can you get Good job on the course so far! to show? How can you get the name to be favorite instructor?

Using Babel In Production

The examples we have seen so far work perfectly fine, but you may have noticed that the websites are rather slow. The reason for the slow down is that we are transpiling our code on the client side (the browser is downloading babel and doing the work of transpiling from JSX to plain JavaScript). We need a better tool for transpiling our code. And we need to make sure that transpiling doesn't happen on the client side.

Webpack is going to help us transpile our JSX. Webpack is a very helpful tool, but it also has a very steep learning curve. Do not worry though! With a little bit a practice you will get the hang of it. Not only does it allow us to easily include babel, it also gives us access to some of the best and latest features in JavaScript, specifically modules. We'll talk about webpack and JavaScript modules in the next chapter.

Exercise

Complete the JSX exercises.

When you're ready, move on to Webpack

Continue