JSX

Understand JSX — the syntax extension that makes React feel like writing HTML in JavaScript. Learn how it compiles, what rules it enforces, and how senior engineers use it in production.

Last reviewed: January 2025

·React 16+React 18React 19
✅
Quick Understanding: JSX is JavaScript with HTML-like syntax. When you write <Button label="Save" />, Babel compiles it to React.createElement(Button, { label: "Save" }). It is not HTML — it is syntactic sugar over plain JavaScript function calls. The browser never sees JSX; it always sees compiled JS.

🔍 What Is It?

JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write UI structure inline with your logic. It looks like HTML but behaves like JavaScript.

  • →JSX compiles to React.createElement() calls (React 17+ uses the new JSX transform — no import needed)
  • →Every JSX element is a function call that returns a React element object
  • →JSX is not a template language — it has the full power of JavaScript
  • →Self-closing tags are required: <img />, <br />, <Input />
  • →class becomes className, for becomes htmlFor (reserved JS words)
  • →Inline styles are objects: style={{ color: 'red', fontSize: 14 }}

🎯 Why Do We Need It?

Before JSX, writing React looked like this:

React.createElement('div', { className: 'card' },
  React.createElement('h2', null, 'Title'),
  React.createElement('p', null, 'Content')
)

With JSX:

<div className="card">
  <h2>Title</h2>
  <p>Content</p>
</div>

JSX makes component trees readable, maintainable, and reviewable. Without it, deeply nested UIs become unreadable noise. It also enables tooling — linters, formatters, and IDEs understand JSX structure.

🏗️ What Happens in Real Projects?

JSX is used in every React component in every React project. In enterprise apps:

  • →Conditional rendering — {isLoggedIn && <Dashboard />} or ternaries
  • →List rendering — {items.map(item => <Card key={item.id} data={item} />)}
  • →Dynamic class names — className={btn ${variant}} or libraries like clsx
  • →Spreading props — <Input {...register('email')} /> (React Hook Form pattern)
  • →Fragments — <><Header /><Main /><Footer /></> when no wrapper div is needed

⚙️ How It Works

Compilation pipeline:

  1. You write JSX in .tsx / .jsx files
  2. Babel (or SWC/esbuild) transforms JSX to React.createElement() calls
  3. React 17+ new JSX transform auto-imports from react/jsx-runtime — no manual import React needed
  4. At runtime, createElement returns a plain JS object: { type, props, key, ref }
  5. React's reconciler compares these objects to the previous render (diffing)
  6. Only changed DOM nodes are updated

Key rules:

  • →Every JSX expression must have a single root element (or Fragment)
  • →JavaScript expressions go inside {} — not statements (no if, for directly)
  • →null, undefined, false render nothing — useful for conditional rendering

💻 Example

JSX Patterns You Will Use Every Day — From basic syntax to real-world conditional and list rendering patterns.

tsx
// JSX compiles to: React.createElement('div', { className: 'card' }, ...)
const Card = ({ title, count, active }: CardProps) => (
  <div
    className={`card ${active ? 'card--active' : ''}`}
    style={{ borderRadius: 8 }}
  >
    {/* Comments inside JSX use this syntax */}
    <h2 className="card__title">{title}</h2>

    {/* Conditional rendering — ternary */}
    {count > 0
      ? <span className="badge">{count}</span>
      : <span className="badge badge--empty">0</span>
    }

    {/* Short-circuit: only renders when active is true */}
    {active && <span className="status">Active</span>}
  </div>
);

🤔 Common Confusions

❓ Is JSX HTML?

No. JSX looks like HTML but it compiles to JavaScript. Key differences: className not class, htmlFor not for, camelCase event names (onClick not onclick), self-closing required, inline styles are objects not strings. Treat JSX as JavaScript with HTML-like syntax, not HTML.

❓ Why can I not use if statements directly in JSX?

JSX curly braces accept expressions, not statements. An if block is a statement. Use ternaries (condition ? a : b) for inline conditionals, or move complex logic to a variable above the return statement. For multi-branch logic, a helper function returning JSX is clearest.

❓ Why does rendering 0 show the number on screen?

Short-circuit {count && <Component />} evaluates to 0 (falsy number) when count is 0 — and React renders 0 as text. Fix: use {count > 0 && <Component />} or {!!count && <Component />}. This is one of the most common JSX bugs in production.

🚨 Common Production Issues

**Bug: Rendering 0 unexpectedly** — {items.length && <List />} renders "0" when array is empty. Fix: {items.length > 0 && <List />}.

**Bug: Missing key prop in lists** — Causes incorrect DOM updates during reorders/deletions. Always use stable unique IDs, never array index for dynamic lists.

**Bug: Mutating objects in JSX** — Passing new object literals as props on every render ({style={{ color: 'red' }}) creates new references each render, breaking memoization. Extract to constants outside the component.

**Performance: Inline arrow functions in JSX** — <Button onClick={() => handleClick(id)} /> creates a new function every render. Fine for most cases, but breaks React.memo. Use useCallback if the child is memoized.

✅ Best Practices

Keep JSX readable — if your return statement is longer than 40 lines, extract sub-components

Use Fragments (<></>) instead of wrapper divs to avoid unnecessary DOM nodes

Always provide meaningful key props for list items — use entity IDs, never array index

Use clsx or classnames library for dynamic class names — avoids messy template literal strings

Extract complex conditional logic to named variables above the return — improves readability

Use htmlFor on labels and id on inputs — JSX accessibility matters from day one

🏛️ Architect's Note

Senior Architect's Perspective

JSX is the most read and reviewed code in your codebase — every PR reviewer reads it. Invest in JSX clarity. A component's JSX should tell a story: what is being rendered, under what conditions, with what data. If you need a comment to explain a JSX block, consider extracting it into a named sub-component instead. In large teams, consistent JSX patterns (how you handle conditionals, lists, and props) reduce cognitive load significantly. Establish a team style guide for JSX early.

💬 Frequently Asked Questions

Do I need to import React in every file with JSX?

Not since React 17. The new JSX transform auto-imports the necessary runtime. If you are on React 16 or older, yes — import React from 'react' is required at the top of every JSX file.

Can I write JSX without Babel?

Technically yes — you can write React.createElement() calls directly. But no one does this in practice. Every modern React setup (Vite, CRA, Next.js) includes Babel or SWC for JSX transformation. It is a non-issue in real projects.

What is the difference between JSX and TSX?

.jsx is JSX in JavaScript. .tsx is JSX in TypeScript. The only difference is TypeScript type-checking. In modern projects, use .tsx for all component files — even if you are not heavily using TypeScript yet, it is easier to migrate.

Why does JSX use className instead of class?

Because class is a reserved keyword in JavaScript (used for ES6 classes). Since JSX compiles to JavaScript, using class would create a syntax conflict. React chose className as the equivalent. This is one of the first things new React developers learn.

🎯 Key Takeaways

1JSX is syntactic sugar — it compiles to React.createElement() calls
2JSX is not HTML — use className, htmlFor, camelCase events, and self-closing tags
3Curly braces {} embed JavaScript expressions — not statements
4Always use stable unique keys for list items — never array index for dynamic lists
5Short-circuit {count && <X />} renders "0" when count is 0 — use {count > 0 && <X />}
6Fragments avoid unnecessary wrapper DOM nodes — prefer <></> over <div>
7React 17+ new JSX transform means no manual import React needed

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide React learning path

Browse the full React topic collection and learning order on SplashRide.

React Interview Prep

Practice React interview questions and scenario-based answers.

Frontend Engineer Career Path

A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.

Python Developer Career Path

A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.

Components

Master React components — the fundamental building blocks of every React application. Learn component design, composition patterns, and how senior engineers structure components in enterprise projects.

Props

Master React props — the mechanism for passing data and behaviour between components. Learn prop design, TypeScript typing, and the patterns senior engineers use in real enterprise applications.