Grokking React Fundamentals
Vote

0% completed

​

Understanding JSX

What Happens to JSX

Why React Uses JSX

Embedding JavaScript With Curly Braces

Attributes in JSX

Every Tag Must Be Closed

One Parent Element

Comments in JSX

The second line below is neither a string nor HTML, yet it sits in a JavaScript file and assigns a value to a constant:

const name = "React"; const element = <h1 className="header">Welcome to {name}!</h1>;

This HTML-like markup inside JavaScript is called JSX. JSX is a syntax extension for JavaScript. It adds tags to the language so that you can describe a piece of the user interface where you write the logic that controls it. The name is commonly read as "JavaScript XML", because the tags follow XML rules, such as every tag being closed. React uses JSX to describe what each part of the screen should show.

What Happens to JSX

Browsers do not understand JSX. Before your code reaches the browser, a compiler such as Babel or esbuild, run by your project's build tool, compiles every JSX tag into an ordinary JavaScript function call. For the two lines above, the compiler produces this:

import { jsxs } from "react/jsx-runtime"; const name = "React"; const element = jsxs("h1", { className: "header", children: [ "Welcome to ", name, "!" ] });

The tag name becomes the first argument, and the attributes and the content become properties of one object. When this code runs, the function call returns a plain JavaScript object that describes the heading. Printing its type and props shows the following:

{"type":"h1","props":{"className":"header","children":["Welcome to ","React","!"]}}

This object is a React element. It is only a description; nothing is on the screen yet. When React renders the element, it creates the real DOM node, and the page then contains this HTML:

<h1 class="header">Welcome to React!</h1>

The diagram follows the heading through those three stages. Watch how the value of name, which is still a separate item in the element object, becomes part of the text only in the final HTML.

The heading written in JSX is compiled into a jsxs call, the call returns a React element object, and React turns that object into an h1 node in the page.
The heading written in JSX is compiled into a jsxs call, the call returns a React element object, and React turns that object into an h1 node in the page.

Why React Uses JSX

You could write every jsxs call by hand, and React would work the same way, so JSX is not required. In practice, almost every React project uses it, for three reasons.

First, JSX is easier to read. A nested layout of headings, lists and buttons looks like the HTML it produces, while the same layout written as nested function calls is hard to follow.

Second, the markup and the logic that controls it stay in one place. Inside JSX, you can use JavaScript variables, function calls and calculations directly, as the rest of this lesson shows.

Third, mistakes appear before the page runs. Because the compiler reads every tag, it stops with an error when a tag is not closed or when a closing tag does not match its opening tag. For the line <h1>Hello</h2>, esbuild reports Unexpected closing "h2" tag does not match opening "h1" tag. Code editors use the same information to offer autocompletion and to mark errors as you type.

Embedding JavaScript With Curly Braces

The heading in the first example contains {name}. Curly braces switch from markup back to JavaScript. Whatever is inside them is evaluated, and the result appears in the output. In the example, the braces hold the variable name, so the heading shows "Welcome to React!".

The braces accept any JavaScript expression. An expression is a piece of code that produces a value, such as a variable, a calculation like count * 2, a function call like formatDate(today) or a method call like name.toUpperCase().

The following example uses the ternary operator to choose between the singular and the plural form:

const count = 5; const message = count > 1 ? `${count} items` : `${count} item`; const element = <h1>You have {message}</h1>;

With count set to 5, the result is <h1>You have 5 items</h1>. With count set to 1, the condition is false and the result is <h1>You have 1 item</h1>.

Statements cannot go inside the braces, because a statement does not produce a value. An if block, a for loop or a variable declaration placed between { and } is a syntax error.

To choose between two pieces of output, use an expression such as the ternary operator, as above. To repeat output for every item in an array, use the array's map method, which returns a value. The Conditional Rendering and Lists chapters explain both patterns in detail.

Attributes in JSX

JSX tags accept attributes, just as HTML tags do, but their names follow JavaScript rules rather than HTML rules.

Most attribute names are written in camelCase, where each word after the first starts with a capital letter. For example, the HTML attributes onclick and tabindex become onClick and tabIndex. Two names change completely, because class and for are reserved words in JavaScript. You write className instead of class, and htmlFor instead of for.

<h1 className="header">Welcome to React!</h1> <label htmlFor="name">Name:</label>

React translates these names back when it creates the DOM. Rendered, the two lines above produce <h1 class="header"> and <label for="name">. If you write class by mistake, React 19 still applies the class, but it prints a warning in the browser console during development:

Invalid DOM property `class`. Did you mean `className`?

An attribute value can be a fixed string in quotes, as in className="header", or a JavaScript expression in curly braces. With braces, the value is computed when the element is created, so it can depend on your data. The braces can even hold a function, which is how React attaches event handlers:

<button onClick={() => alert('Button clicked!')}>Click Me</button>

Here the value of onClick is an arrow function. React calls it when the user clicks the button, and the browser shows an alert with the text "Button clicked!". The braces hold the function itself. If you wrote onClick={alert('Button clicked!')} instead, alert would run once while the element is created, not when the user clicks. The Handling Events chapter covers this in detail.

Every Tag Must Be Closed

In HTML, some elements, such as <img> and <input>, have no closing tag. JSX follows stricter rules: every tag must be closed. An element without content can close itself with a slash before the final >, which is called a self-closing tag.

const element = <img src="logo.png" alt="Logo" />;

Without the slash, <img src="logo.png" alt="Logo"> is a syntax error, because the compiler keeps looking for a closing </img> tag that never comes. Any element can be self-closing in JSX, not only images and inputs. For example, <div /> is valid and renders as an empty <div></div>.

One Parent Element

A component is a function that returns JSX. Because every JSX tag compiles to one function call that returns one object, a component can return only one top-level element, in the same way that a JavaScript function can return only one value. Two tags placed side by side, such as return (<h1>Hello</h1><p>This is React</p>);, are a syntax error.

To return several elements, wrap them in one parent. The simplest parent is a <div>:

function App() { return ( <div> <h1>Hello</h1> <p>This is React</p> </div> ); }

The <div> appears in the page, around the other two elements:

<div><h1>Hello</h1><p>This is React</p></div>

Sometimes you need a parent for JSX, but you do not want an extra element in the page, because it would break a CSS layout or add a meaningless node to the DOM. For this case, React provides the Fragment, written as an empty tag pair <> and </>:

function App() { return ( <> <h1>Hello</h1> <p>This is React</p> </> ); }

The Fragment groups the elements for JSX and then disappears. The page receives only the two children:

<h1>Hello</h1><p>This is React</p>

Use a <div> when you need the wrapper in the page, for example to style it, and a Fragment when you need it only to satisfy the one-parent rule.

Comments in JSX

Between JSX tags, the text is treated as content, so a JavaScript comment such as // This is a comment appears on the screen as text. The following element shows the problem:

<div> // This is not a comment <h1>Hello, World!</h1> </div>

It renders as <div>// This is not a comment<h1>Hello, World!</h1></div>, with the comment visible on the page. To write a comment between tags, switch to JavaScript with curly braces and use a block comment inside them:

<div> {/* This is a comment inside JSX */} <h1>Hello, World!</h1> </div>

This renders as <div><h1>Hello, World!</h1></div>. The braces contain only a comment, so they produce no value, and nothing appears in the page.

Reading Progress

0%


Vote for new content

On This Page

What Happens to JSX

Why React Uses JSX

Embedding JavaScript With Curly Braces

Attributes in JSX

Every Tag Must Be Closed

One Parent Element

Comments in JSX