Quiz

What is JSX and how does it work?

Topics
React

TL;DR

JSX stands for JavaScript XML. It is a syntax extension for JavaScript that allows you to write HTML-like code within JavaScript. JSX makes it easier to create React components by allowing you to write what looks like HTML directly in your JavaScript code. Under the hood, JSX is transformed into JavaScript function calls, typically using a tool like Babel. For example, <div>Hello, world!</div> in JSX is transformed into React.createElement('div', null, 'Hello, world!').


What is JSX and how does it work?

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.

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.
  • URL-valued attributes such as href and src are not sanitized by React — href="javascript:..." will execute if the URL string comes from an attacker-controlled source. Validate URLs yourself.

Further reading

Edit on GitHub