Quiz

What is JSX and how does it work?

Topics
React

TL;DR

JSX is a syntax extension for JavaScript that lets you describe UI with HTML-like markup inside JavaScript. A build tool transforms it into ordinary function calls before the browser runs it. With the modern automatic runtime, <div>Hello, world!</div> becomes a call to a helper from react/jsx-runtime; the older classic transform used React.createElement.


What is JSX and how does it work?

JSX is syntax that a build tool transforms into calls producing React element descriptions; browsers do not execute JSX directly.

What is JSX?

JSX is a syntax extension for JavaScript that lets you describe UI trees with an HTML-like syntax. Although it was popularized by React, JSX itself is a separate spec and is also used by other libraries such as Preact and Solid. TypeScript supports it natively in .tsx files.

How does JSX work?

JSX is not valid JavaScript by itself. A compiler — typically Babel or the bundler's built-in transform (SWC, esbuild, Oxc) — converts JSX into ordinary JavaScript function calls before the browser sees it.

JSX syntax

JSX allows you to write HTML-like tags directly in your JavaScript code. For example:

const element = <h1>Hello, world!</h1>;

Transformation process

Since React 17 (2020), the default transform is the automatic JSX runtime. Instead of compiling to React.createElement, the compiler imports jsx / jsxs helpers from react/jsx-runtime and emits calls to those. A consequence is that you no longer need to import React from 'react' just to use JSX:

// Source
const element = <h1>Hello, world!</h1>;
// Output with the automatic runtime (conceptually)
import { jsx as _jsx } from 'react/jsx-runtime';
const element = _jsx('h1', { children: 'Hello, world!' });

The older "classic" transform compiled the same JSX to React.createElement('h1', null, 'Hello, world!') and required React to be in scope. The classic form is still useful as a mental model for what JSX desugars to, but new projects should use the automatic runtime.

Regardless of which transform is configured, JSX becomes ordinary JavaScript before React receives an element description:

JSX transformation and rendering pipeline

Embedding expressions

You can embed JavaScript expressions inside JSX using curly braces {}. For example:

const name = 'John';
const element = <h1>Hello, {name}!</h1>;

Attributes in JSX

You can use quotes to specify string literals as attributes and curly braces to embed JavaScript expressions. For example:

const element = <img src={user.avatarUrl} alt="User Avatar" />;

Because JSX attributes compile to JavaScript object keys, a few HTML attribute names are renamed to avoid clashing with reserved words or to follow JS camelCase conventions:

  • class becomes className
  • for becomes htmlFor
  • Event handlers are camelCased: onclick becomes onClick, onchange becomes onChange
  • Most other DOM properties (tabIndex, readOnly, maxLength, etc.) use camelCase

Fragments

To return multiple elements without an extra wrapper DOM node, use a fragment. The shorthand syntax is <>...</>:

function List() {
return (
<>
<li>One</li>
<li>Two</li>
</>
);
}

The longer form <Fragment key={id}>...</Fragment> is needed when you must pass a key.

JSX is an expression

After compilation, JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. This means you can use JSX inside if statements, assign it to variables, and pass it as a prop or argument.

JSX prevents injection attacks

By default, React DOM escapes any values embedded in JSX with {} before rendering them, which neutralizes the most common XSS vector — injecting markup via untrusted strings:

const userInput = '<img src=x onerror="alert(1)" />';
const safe = <div>{userInput}</div>; // rendered as text, not as HTML

This protection is not absolute. Two notable escape hatches still bypass escaping and can introduce XSS if fed untrusted data:

  • dangerouslySetInnerHTML={{ __html: ... }} injects raw HTML into the DOM.
  • React 19 blocks javascript: URLs in URL-valued attributes such as href and src. You should still validate attacker-controlled URLs against the schemes and destinations your application permits because other schemes, redirects, and resource types can carry their own risks.

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise
Check your understanding Exercise

What happens to JSX before a typical browser executes the application?