JSX (JavaScript XML) is more than just a convenient way to write markup in your React components. It's a powerful syntax extension that fully unlocks the declarative and component-based nature of React. Understanding its rules and how it bridges the gap between JavaScript logic and UI representation is the most critical step in mastering React.
The 3 Golden Rules of JSX
While JSX looks like HTML, it has a few strict rules you must follow, which are enforced by the compiler:
- Return a Single Root Element: A component's `return` statement can only return one "top-level" element. If you need to return multiple elements, wrap them in a parent `<div>` or, more commonly, a Fragment (
<>...</>), which doesn't add an extra node to the DOM. - All Tags Must Be Closed: Unlike HTML, JSX is strict. Any tag you open must be closed. Tags that are "self-closing" in HTML, like `<img>` or `<br>`, *must* be self-closed in JSX: `<img />`, `<br />`.
- Use `camelCase` for Props: JSX attributes are JavaScript props. Since `class` and `for` are reserved keywords in JavaScript, JSX uses `className` and `htmlFor` instead. This applies to many attributes: `onclick` becomes `onClick`, `tabindex` becomes `tabIndex`.
Embedding JavaScript with ``
The true power of JSX comes from the curly braces: ``. Inside them, you can write **any valid JavaScript expression**. This allows you to make your UI dynamic.
- Displaying Data: `<h1>{user.name}</h1>`
- Setting Attributes: `<img src={user.avatarUrl} />`
- Conditional Logic (Ternary): `<p>{isLoggedIn ? 'Welcome back!' : 'Please log in'}</p>`
- Mapping Arrays to Elements: The `.map()` method is the standard way to render lists:
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>Notice the `key` prop. This is a special prop that React uses to identify which items have changed, been added, or been removed, allowing for highly efficient updates.
Under the Hood: JSX to `React.createElement()`
Browsers do not understand JSX. Your code only runs because a **compiler** (like Babel) transforms your JSX before it ever reaches the browser.
When Babel sees this JSX:
const element = <h1 className="title">Hello</h1>;It transforms it into this plain JavaScript function call:
const element = React.createElement("h1", { className: "title" }, "Hello");This function, `React.createElement()`, doesn't create a DOM node. It returns a simple JavaScript **object** (a "React Element") that describes what *should* be rendered.
// The object returned looks like this:
{
type: 'h1',
props: {
className: 'title',
children: 'Hello'
}
}React then takes this object, compares it to the previous one, and calculates the most efficient way to update the actual browser DOM to match. This object-based intermediate step is the foundation of the Virtual DOM and is what makes React so fast.
Key Takeaway: JSX is a developer-friendly syntax that allows you to describe UIs declaratively. It is compiled into `React.createElement()` calls, which produce JavaScript objects. React uses these objects to efficiently manage and update the DOM.