Skip to content
WANCODE
BM

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)

JSX
const title = (
  <h1 className="title">
    Hello, {name}!
  </h1>
);

What it becomes (classic transform)

JavaScript
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.

JSX
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
class is a reserved word in JavaScript, so JSX uses className="card". (for on labels becomes htmlFor.)
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-* and data-* stay as they are.)

HTML habit (breaks or warns)

JSX
<p class="note" style="color: red">
  Hot!<br>
</p>

JSX

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

JSX
return (
  <h1>Menu</h1>
  <p>Fresh daily</p>
);

Fragment

JSX
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

Q1

With the classic transform, what does <p className="tip">Hi</p> compile to?

Q2

Which one is valid inside JSX braces?

Q3

Why does inline style use double braces: style={{ color: "red" }}?

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.
Preview

Console output from your code appears here.

Step 1 of 3