Home/Learn/React/JSX — Markup That Is Really JavaScript

JSX — Markup That Is Really JavaScript

Beginner
Fundamentals

JSX compiles to function calls. Knowing that explains every rule it has, including the ones that look arbitrary.

Overview

JSX looks like HTML inside JavaScript, which makes people treat it as a template language with strange rules. It is not a template language — it is syntax sugar over function calls, and every element you write becomes a call producing a plain object. That is why attributes use JavaScript names rather than HTML ones, why you can only interpolate expressions and not statements, and why a component must return a single root. None of these are arbitrary once you have seen what JSX compiles into.

What It Compiles To

One transformation explains the whole syntax.

JSX is function calls
// You write
<button className="primary" onClick={handleRun}>Run</button>

// The compiler produces
jsx('button', { className: 'primary', onClick: handleRun, children: 'Run' })

// which evaluates to a plain object describing what to render:
{ type: 'button', props: { className: 'primary', ... } }

// Consequences that follow directly:
//   - 'class' is a reserved word    -> className
//   - 'for' is a reserved word      -> htmlFor
//   - attributes are JS properties  -> onClick, tabIndex, readOnly
//   - a component returns ONE value -> one root element, or a Fragment

<>                            {/* Fragment — groups without a wrapper div */}
  <Header />
  <Main />
</>

// A capital letter means "component"; lowercase means "DOM element".
<button />   // the HTML button
<Button />   // your component

Expressions and Conditionals

Braces take an expression, never a statement. That constrains how you write conditionals inside markup.

Expressions only, and the falsy-0 trap
<p>{user.name}</p>
<p>{items.length > 0 ? 'Ready' : 'Empty'}</p>
<p>{formatDate(attempt.submittedAt)}</p>

// if / for / switch are statements — they go ABOVE the return
if (!user) return <SignInPrompt />

// Conditional rendering, with the classic trap
{count && <Badge count={count} />}       // renders "0" when count is 0
{count > 0 && <Badge count={count} />}   // correct
{items.length ? <List /> : <Empty />}    // also fine

// These render nothing at all: null, undefined, false, true, ''
// A number does render, which is why 0 leaks onto the screen.

// Attributes take expressions too
<img src={problem.cover} alt={problem.title} />
<button disabled={isSubmitting}>Save</button>
<div className={`card ${isActive ? 'active' : ''}`} />
<Row {...problem} />                     // spread props

Rules Worth Knowing Early

A short list that covers most JSX confusion.

style objects, comments, escaping
// Comments inside JSX need braces
{/* like this */}

// style takes an object with camelCase keys, not a string
<div style={{ marginTop: 8, backgroundColor: 'red' }} />

// Self-close void elements
<img />  <br />  <input />

// Whitespace and newlines between elements are collapsed;
// explicit spaces use {' '}
<span>Solved{' '}<strong>42</strong></span>

// Rendering raw HTML is deliberately awkward, because it is unsafe
<div dangerouslySetInnerHTML={{ __html: sanitised }} />

// Everything else is escaped automatically:
<p>{userComment}</p>       // safe — script tags render as text

Key Points to Remember

  • 1JSX compiles to function calls returning plain objects — every syntax rule follows from that
  • 2className and htmlFor exist because class and for are reserved JavaScript words
  • 3Braces accept expressions only; if, for and switch go above the return statement
  • 4{count && <Badge/>} renders a literal 0 when count is 0 — compare explicitly instead
  • 5React escapes interpolated values by default; dangerouslySetInnerHTML is the deliberate exception

Interview Questions

Sign in to ask Aria
1

What does JSX compile to, and why does that matter?

Easy
2

Why does {items.length && <List/>} sometimes render a 0?

Medium
3

Why must a component return a single root element, and how do Fragments help?

Easy

Ask Aria about JSX — Markup That Is Really JavaScript

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…