JSX Explained
15 minIntermediateReact
In this lesson
- ▸Put JavaScript values and calculations into JSX with
{ } - ▸Use the JSX versions of HTML habits:
className,style={{ }}, self-closing tags - ▸Return one root element, or a Fragment
<>…</> - ▸Explain that JSX compiles to plain function calls that create objects
The big idea
JSX is a friendlier way to write JavaScript function calls. Every tag becomes a call that returns an object describing the UI — which is why it follows JavaScript's rules, not HTML's.
The tags in your components look like HTML, but the browser never sees them. Before your code runs, a compiler (in WANCode it's Sucrase; in real projects usually Babel, esbuild or SWC) turns every JSX tag into a JavaScript function call.
What you write (JSX)
const title = (
<h1 className="title">
Hello, {name}!
</h1>
);What it becomes (classic transform)
const title = React.createElement(
"h1",
{ className: "title" },
"Hello, ",
name,
"!"
);createElement(type, props, ...children) returns a plain object, roughly { type: "h1", props: { className: "title", children: [...] } }. React reads these objects to build the real DOM.
The modern "automatic" runtime
Since React 17, tools usually compile JSX to jsx("h1", { className: "title", children: … }) imported automatically from react/jsx-runtime, instead of React.createElement. The result is the same kind of object — and it's why you no longer need import React at the top of every file.
Curly braces: a window into JavaScript
Inside JSX, { } means "evaluate this JavaScript and put the result here". Anything that produces a value works: variables, maths, function calls, ternaries. Statements like if or for don't — they don't produce a value.
const user = { name: "Mei Ling", points: 1250 };
const isMember = true;
<div>
<h2>{user.name.toUpperCase()}</h2>
<p>Points: {user.points}</p>
<p>Next reward in {2000 - user.points} points</p>
<p>{isMember ? "Member price" : "Normal price"}</p>
{/* this is a comment inside JSX */}
</div>HTML habits that change in JSX
- className
classis a reserved word in JavaScript, so JSX usesclassName="card". (foron labels becomeshtmlFor.)- style={{ }}
- Style takes a JavaScript object, not a string. Outer braces = "JavaScript here", inner braces = the object. Property names are camelCase:
fontWeight,backgroundColor. Plain numbers mean px:padding: 8. - Self-closing tags
- Every tag must be closed. Empty elements end with
/>:<img />,<br />,<hr />,<input />.<hr>alone is a syntax error. - camelCase attributes
- Most attributes become camelCase:
onclick→onClick,tabindex→tabIndex. (aria-*anddata-*stay as they are.)
HTML habit (breaks or warns)
<p class="note" style="color: red">
Hot!<br>
</p>JSX
<p className="note" style={{ color: "red" }}>
Hot!<br />
</p>One parent per return — or a Fragment
A function can only return one value, and each JSX tag is one function call. So a component must return a single root element. If you don't want an extra <div> in the page, wrap siblings in a Fragment: <>…</>. It groups them without adding anything to the DOM.
Syntax error: two roots
return (
<h1>Menu</h1>
<p>Fresh daily</p>
);Fragment
return (
<>
<h1>Menu</h1>
<p>Fresh daily</p>
</>
);The receipt prints the literal words customer, quantity and item instead of the values in the variables above. Use { } so that:
- the heading says Receipt for Hafiz,
- the line says 3 x Roti canai,
- the total is calculated from quantity * price and shown with two decimals: RM5.40.
Checks
- The heading shows the customer's name
- The line shows quantity and item
- The total shows RM5.40
- The total is calculated in JSX, not typed in
Check understanding
What you learned
- ✓JSX compiles to function calls (
createElement/jsx) that return plain objects describing the UI. - ✓
{ }inserts any JavaScript expression: variables, maths, method calls, ternaries. - ✓Use
className,style={{ camelCase: value }}and close every tag (<hr />). - ✓Return one root element; use a Fragment
<>…</>to group siblings without an extra wrapper.
Console output from your code appears here.