JSX is a syntax extension that lets you write HTML-like markup in JavaScript — it compiles to function calls (React.createElement or the automatic jsx runtime) and provides XSS protection by escaping values by default.
JSX compiles to React.createElement() calls (or jsx() with React 17+ automatic runtime) — it's syntax sugar, not a template language.
className instead of class, htmlFor instead of for, camelCase events/attributes, required self-closing tags, and object-style inline styles.
Curly braces {} embed any JavaScript expression — variables, function calls, ternaries. Statements (if/else, for) cannot be used directly.
Ternary for if/else, logical AND (&&) for show/hide, early return for loading states, or null to render nothing.
JSX escapes all embedded values by default — user input is treated as text, not HTML. dangerouslySetInnerHTML is the explicit opt-out.
JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write HTML-like markup directly in your JavaScript code. It's not required to use React, but virtually all React code uses it because it makes component structure visual and intuitive.
JSX is not valid JavaScript — it must be compiled. Before React 17, Babel transformed <div className="hello">Hi</div> into React.createElement('div', { className: 'hello' }, 'Hi'), which is why every file needed import React from 'react'. Since React 17, the automatic JSX transform compiles to _jsx('div', { className: 'hello', children: 'Hi' }) — no React import required. The compiled output creates JavaScript objects (React elements) that describe what should appear on screen.
className instead of class (because class is a reserved word in JavaScript)htmlFor instead of for on labels (same reason)onClick, onChange, onSubmit (not onclick)<img />, <input />, <br /> (HTML allows <img> but JSX doesn't)style accepts an object with camelCase properties: style={{ backgroundColor: 'red', fontSize: '16px' }}tabIndex, autoFocus, readOnly<>...</> (Fragment) to wrap multiple elements without adding a DOM nodeCurly braces {} embed any valid JavaScript expression: variables, function calls, ternary operators, array methods. Statements (if/else, for loops, switch) cannot be used directly inside JSX — use ternary expressions or extract logic before the return.
Three common patterns:
{isLoggedIn ? <Dashboard /> : <Login />}{hasError && <ErrorMessage />} — renders nothing when hasError is falsy (but beware: {0 && <Component />} renders 0, not nothing — use {count > 0 && <Component />} instead)if (!data) return <Loading />; before the main JSXnull to render nothingJSX escapes all embedded values by default — if you insert user input via {userInput}, it's treated as text, not HTML. This prevents cross-site scripting (XSS) attacks. To deliberately render HTML, you must use dangerouslySetInnerHTML={{ __html: sanitizedContent }} — the name is intentionally scary to discourage unsafe usage.
Since JSX compiles to function calls, you can assign JSX to variables, pass it as props, return it from functions, and put it in arrays. This is what makes React's composition model powerful — JSX elements are just values.
JSX is syntax sugar that compiles to React.createElement() (or jsx() with the automatic runtime). It is not a template language — it has the full power of JavaScript. The main differences from HTML are className, htmlFor, camelCase attributes, required self-closing tags, and object-style style props. JSX escapes values by default for XSS protection.
Fun Fact
When React was first introduced with JSX in 2013, many developers were horrified — mixing HTML-like syntax in JavaScript felt like a violation of separation of concerns. The backlash was so strong that the React team created a JSX-free API (React.createElement) as an alternative. Within a year, JSX became the standard and is now universally accepted.