Course: Section

Get Started with Modern React: Step by Step

Episode: Title

S02・V04: Introducing JSX

Date Created: July 17th, 2019
Last Updated: 27 days ago

Objectives
  1. We will examine JSX in more detail.
  2. We will show examples of how JSX is used in React.
Watch Video
Duration: 7m 32s

JSX

JSX is a syntax extension to JavaScript. Using JSX with React is recommended to describe what the UI should look like. JSX compiles to React elements, which we discussed in the previous video. We can comment out our header element on line 6, and uncomment the JSX version in the line above.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const rootNode = document.getElementById("root");
const element = <h1>Hello, World!</h1>;// const element = React.createElement("h1", {id: "header"}, "Hello, World!");
ReactDOM.render(element, rootNode);

JSX Props

Now, the element we created in line 6 has a props object, with an id of header. One way to add props to a JSX element is to specify a string literal as an attribute to the tag. In our example, we can add an id attribute, with a value of header as a string literal.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const rootNode = document.getElementById("root");
const element = <h1 id="header">Hello, World!</h1>;// const element = React.createElement("h1", {id: "header"}, "Hello, World!");

ReactDOM.render(element, rootNode);

We can see that our red header color has been successfully applied.

Since JSX is closer to JavaScript than HTML, we camel-case attribute names in JSX. For example, the global HTML attribute contenteditable is written all lower-case, but in JSX, we camel-case the prop contentEditable.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const rootNode = document.getElementById("root");
const element = <h1 id="header" contentEditable>Hello, World!</h1>;// const element = React.createElement("h1", {id: "header"}, "Hello, World!");

ReactDOM.render(element, rootNode);

Now our header is editable. Let’s now remove the contentEditable and id attributes, and delete the commented out line.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const rootNode = document.getElementById("root");
const element = <h1>Hello, World!</h1>;
ReactDOM.render(element, rootNode);

Now, let’s go to public/index.html and remove the styles.

public/index.html
<!DOCTYPE html>
<html lang="en">

  <head>
    <title>React App</title>
  </head>

  <body>
    <div id="root"></div>
  </body>

</html>

Embedding Expressions in JSX

Now, we will return to src/index.js. We can embed JavaScript expressions within JSX. Define a constant name with the value of the string literal John Doe. Instead of the word World in our header, we can embed the name within the JSX element, within curly braces.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const name = "John Doe";const rootNode = document.getElementById("root");
const element = <h1>Hello, {name}!</h1>;
ReactDOM.render(element, rootNode);

We can put any valid JavaScript expression inside the curly braces in JSX. For example, we can call a function. Let’s define the function formatName(). It will return the user’s first name and last name. Now, we will add some user data. It will be an object with fields for the first name, last name, and photoUrl.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

function formatName(user) {  return `${user.firstName} ${user.lastName}`;}
const user = {  firstName: "Jane",  lastName: "Roe",  photoUrl: "https://picsum.photos/id/1027/200/100"};
const rootNode = document.getElementById("root");
const element = <h1>Hello, {formatName(user)}!</h1>;
ReactDOM.render(element, rootNode);

JSX is an Expression Too

Note that after compilation, JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. This means that you can use JSX inside of if statements and for loops, you can assign JSX to variables, accept JSX as arguments, and return JSX from functions.

Let’s define a function that gets a greeting for a user. If there is a user, then return a greeting using their formatted name. Otherwise, return a generic greeting.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

function formatName(user) {
  return `${user.firstName} ${user.lastName}`;
}

const user = {
  firstName: "Jane",
  lastName: "Roe",
  photoUrl: "https://picsum.photos/id/1027/200/100"
};

function getGreeting(user) {  if (user) {    return `Hello, ${formatName(user)}!`;  }  return `Hello, Stranger.`;}
const rootNode = document.getElementById("root");
const element = <h1>{getGreeting(user)}</h1>;
ReactDOM.render(element, rootNode);

Now, let’s see what happens when we set our user to null.

src/index.js
const user = null;

We see our page now shows Hello, Stranger.. Now that we have illustrated that, let’s undo setting user to null.

Self-Closing JSX Tags

If a tag is empty, you may close it immediately, as you would do in XML. For example, an img tag is closed immediately.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

function formatName(user) {
  return `${user.firstName} ${user.lastName}`;
}

const user = {
  firstName: "Jane",
  lastName: "Roe",
  photoUrl: "https://picsum.photos/id/1027/200/100"
};

function getGreeting(user) {
  if (user) {
    return `Hello, ${formatName(user)}!`;
  }
  return `Hello, Stranger.`;
}

const rootNode = document.getElementById("root");
// const element = <h1>{getGreeting(user)}</h1>;const element = <img src={user.photoUrl} />;
ReactDOM.render(element, rootNode);

Specifying Children with JSX

Instead of using quotes to specify string literals as attributes, you can also use curly braces to embed a JavaScript expression in an attribute. JSX tags may contain several children.

src/index.js
const element = (  <div>    <h1>{getGreeting(user)}</h1>    <img src={user.photoUrl} />  </div>);

JSX Prevents Injection Attacks

As a final point for this video, JSX prevents injection attacks. It is safe to embed user input in JSX. To demonstrate this, let’s first remove the elements we have used up to now. We can also remove the function declarations and the user. Now, let’s prompt the user for some input, which if the user is a hacker, could be malicious code. And, we will create an element embedding the user input received.

src/index.js
import React from "react";
import ReactDOM from "react-dom";

const potentiallyMaliciousUserInput = prompt();
const element = <div>{potentiallyMaliciousUserInput}</div>;const rootNode = document.getElementById("root");

ReactDOM.render(element, rootNode);

Now, we can try to enter a script which is malicious in the prompt input field in Google Chrome:

<script>alert('malicious attack')</script>

By default, React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything that’s not explicitly written in your application. Everything is converted to a string before being rendered. This helps prevent XSS attacks.

Summary

We had a close look at JSX, and we showed several examples of how it is used with React.

Next Up…

In the next video, we will show you how to render React elements to the DOM, and update them.