2.1 JSX & Rendering Elements
← Back to Chapter 2: React Fundamentals
JSX (JavaScript XML) is a syntax extension for JavaScript that allows you to write HTML-like markup directly inside your JavaScript code. It pairs the rendering logic of UI elements with their behavior logic, creating cohesive, declarative components.
1. What is JSX?
Browsers do not understand JSX natively. During the build process, a compiler (such as Babel, SWC, or Vite/esbuild) converts JSX into standard JavaScript function calls.
Behind the Scenes: The JSX Transform
// What you write (JSX):
const element = <h1 className="hero-title">Hello, React!</h1>;
// What the compiler outputs (Classic React.createElement):
const element = React.createElement(
"h1",
{ className: "hero-title" },
"Hello, React!"
);
// What React 17+ outputs (New JSX Transform):
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("h1", {
className: "hero-title",
children: "Hello, React!"
});
The resulting element is a plain JavaScript object describing the DOM node:
{
type: 'h1',
props: {
className: 'hero-title',
children: 'Hello, React!'
}
}
2. Rules of Writing JSX
Rule 1: Return a Single Root Element
Every component must return a single root element. If you need to return multiple adjacent elements without adding an extra <div> to the real DOM, wrap them in a Fragment (<React.Fragment> or <>):
function NavigationBar() {
return (
<>
<a href="/home">Home</a>
<a href="/docs">Docs</a>
<a href="/contact">Contact</a>
</>
);
}
Under the hood, a component is a function returning a JavaScript value. A function cannot return multiple separate objects simultaneously without wrapping them in an array or parent container object.
Rule 2: Close All Tags
Every tag in JSX must be explicitly closed. Self-closing tags require a trailing slash:
// ✅ Correct:
<img src="/logo.png" alt="Logo" />
<input type="text" placeholder="Search..." />
<br />
Rule 3: camelCase Most Attributes
Because JSX turns into JavaScript objects and class and for are reserved keywords in JS:
- Use
classNameinstead ofclass - Use
htmlForinstead offor - Use
tabIndexinstead oftabindex - Inline styles take an object with camelCase properties:
style={{ backgroundColor: "#1e293b", padding: "12px" }}
3. Embedding JavaScript Expressions with {}
Any valid JavaScript expression (something that evaluates to a value) can be embedded inside JSX using curly braces {}:
const user = {
firstName: "Sarwvidya",
lastName: "Sharma",
avatar: "https://avatar.dev/sarvy.png"
};
function formatName(u) {
return `${u.firstName} ${u.lastName}`;
}
function ProfileCard() {
return (
<div className="card">
<img src={user.avatar} alt={formatName(user)} />
<h3>{formatName(user)}</h3>
<p>Calculated score: {10 + 25 * 2}</p>
</div>
);
}
Inside {} you can only place expressions (ternary operations, function calls, variable lookups, .map()). You cannot put statements like if...else, for loops, or switch statements directly inside {}.
4. Rendering Elements into the DOM
In React 18 and 19, the modern entry point uses createRoot from react-dom/client:
// main.jsx / index.jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
React.StrictMode
<React.StrictMode> is a developer-only tool that does not render any visible UI. It:
- Double-invokes functions and lifecycle effects in development to expose unintended side-effects.
- Warns about deprecated APIs and legacy patterns.
- Checks for safe usage of concurrent features.
5. Summary Checklist
- JSX is a declarative syntax sugar for
React.createElement()that produces lightweight Virtual DOM element trees. - All tags must be closed and grouped into a single root (use Fragments
<> ... </>to avoid redundant wrapper divs). - Use
camelCasefor DOM attributes (className,htmlFor,onClick). - Embed any JavaScript expression inside
{}anywhere within text or attributes. - React uses
createRoot(container).render(<App />)to bind the Virtual DOM tree to the browser runtime.