JSX is the syntax extension that lets you write HTML-like markup directly inside JavaScript, and it's how nearly every React component describes its UI. This lesson covers what JSX actually compiles to and the specific rules ā from className to the single-root requirement ā that make it behave differently from plain HTML.
1What is JSX?
JSX stands for JavaScript XML. Although it looks remarkably like HTML, it's actually a syntax extension for JavaScript created by Meta, letting you write UI structures in a visually familiar way while still having the full power of JavaScript embedded directly inside.
This eliminates the need to keep markup and rendering logic in separate files ā a component's structure and its behavior live together in the same JSX expression.
const element = <h1>Hello React!</h1>;Hello React!
2JSX vs HTML Attributes
Because JSX compiles to JavaScript, a handful of HTML attributes conflict with reserved JavaScript keywords and must change. The most common is class, which becomes className in JSX since class is reserved for ES6 class declarations.
The same logic applies elsewhere: for becomes htmlFor, and inline styles must be passed as JavaScript objects rather than plain style strings.
function Welcome() {
return <h1>Hello World</h1>;
}3Embedding Expressions
One of JSX's most powerful features is embedding standard JavaScript expressions directly inside markup. Wrapping a variable, function call, or arithmetic expression in curly braces {} tells React to evaluate that JavaScript and inject its result into the UI, as in <h1>Hello, {name}!</h1>.
This curly-brace syntax is what creates a direct bridge between your application's data and what actually appears on screen.
function Profile() {
return (
<>
<h1>User</h1>
<p>Description</p>
</>
);
}Hello, Alice!
4Calling Functions in JSX
Because curly braces accept any valid JavaScript expression, you aren't limited to injecting plain variables ā you can invoke functions directly inside JSX. If you need to format data, concatenate strings, or compute a value right before rendering, calling a helper function like {format(user)} works exactly the same way.
React executes the function during the render phase and displays whatever string, number, or JSX element it returns.
<h1>React Architect Unlocked!</h1>User: Ada Lovelace
5Step-by-Step Breakdown
What is JSX?. Welcome to JSX! It stands for JavaScript XML. While it looks remarkably like HTML, it is actually a syntax extension for JavaScript created by Meta. JSX allows developers to write UI structures in a syntax that is visually familiar to HTML, but with the full programmatic power of JavaScript directly embedded within it. This fundamental shift eliminates the need to separate logic and markup into different files.
JSX vs HTML Attributes. Because JSX is closer to JavaScript than HTML, there are a few syntax differences you must memorize. The most famous is 'className'. In standard HTML, you use the 'class' attribute to assign CSS classes. However, 'class' is a reserved keyword in JavaScript (used for defining ES6 classes). Therefore, in JSX, you must use 'className'. Similarly, 'for' becomes 'htmlFor', and all inline styles must be passed as JavaScript objects, not strings.
Embedding Expressions. One of the most powerful features of JSX is the ability to embed standard JavaScript expressions directly inside the markup. By wrapping a variable, function call, or mathematical expression in curly braces {}, you command React to evaluate the JavaScript and inject its result into the UI. This creates a seamless bridge between your application's data state and its visual representation on the screen.
Calling Functions in JSX. Because curly braces accept any valid JavaScript expression, you are not limited to just injecting variables. You can invoke functions directly within your JSX. For instance, if you need to format data, concatenate strings, or calculate a specific value right before rendering, you can call a helper function. React will execute the function during the render phase and display whatever string, number, or JSX element is returned.
It is crucial to remember the distinction between JavaScript and HTML when writing JSX. When you need to apply a CSS class to a div element inside your React component, which property name must you use?
- āclass
- āclassName
The Single Root Rule. A strict architectural rule of JSX is that every component must return exactly ONE single root element. Under the hood, JSX compiles down to standard JavaScript function calls that return a single object. You cannot return multiple parallel elements because a JavaScript function cannot return multiple distinct values simultaneously unless they are wrapped in an array or an object. To solve this, you must wrap your sibling elements in a single parent container.
React Fragments. While wrapping elements in a <div> solves the single root rule, it can clutter your DOM with unnecessary nodes, causing styling issues with Flexbox or Grid. To solve this elegantly, React provides 'Fragments'. A Fragment is an invisible wrapper that groups elements together in JSX without rendering an actual HTML node to the browser. The shorthand syntax for a Fragment is empty tags: <></>.
JSX is an Expression. Because JSX ultimately compiles into JavaScript objects, JSX itself is treated as an expression. This means you can confidently use JSX blocks inside 'if' statements, assign them to variables, pass them as arguments to other functions, or return them dynamically based on state. This gives you absolute programmatic control over your UI architecture, allowing you to render completely different structures based on logic.
Self-Closing Tags. In standard HTML, certain tags like <img> or <input> are self-closing and do not require a closing slash. In JSX, the parser is much stricter. Every single tag MUST be properly closed. If an element does not have children, you must explicitly close it with a trailing slash (e.g., <img />). If you forget the slash, the JSX compiler will throw a severe syntax error and your application will crash during the build phase.
You are building a complex layout and need to return a Header, a Main section, and a Footer side-by-side from your component. What is the invisible wrapper you should use to satisfy React's single root rule without polluting the DOM?
- ā<div> wrapper
- ā<> Fragment
Inline Styles in JSX. In standard HTML, inline styles are passed as simple strings. In JSX, however, inline styles MUST be passed as JavaScript objects. The CSS property names must be converted to camelCase (e.g., 'background-color' becomes 'backgroundColor'). Because you are injecting a JavaScript object into a JSX expression, you will notice a double curly-brace syntax: {{ ... }}. The outer braces indicate an expression, and the inner braces denote the object itself.
camelCase Properties. Because JSX is compiled into JavaScript, HTML attributes that consist of multiple words must be written in camelCase. This matches standard JavaScript DOM API conventions. For example, 'onclick' becomes 'onClick', 'tabindex' becomes 'tabIndex', and 'svg' attributes like 'stroke-width' become 'strokeWidth'. This rule applies to almost every multi-word HTML attribute you use inside a React component.
htmlFor vs for. Just like 'className', there is another very important reserved word exception in JSX. In standard HTML forms, you link a label to an input using the 'for' attribute. However, 'for' is a reserved looping keyword in JavaScript. Therefore, in JSX, you must use 'htmlFor' instead. Forgetting this will not immediately break the app, but React will loudly warn you in the console.
Mastery Achieved. JSX mastery achieved! You now understand the fundamental syntax of React components. You know how to embed expressions, utilize Fragments, apply styles as objects, and avoid reserved keyword collisions. You are completely ready to move on to the next major phase: Component Props.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1JSX Renders to Real HTML, So Semantics Still Apply
Because `<div className="btn" onClick={...}>` compiles down to a plain, non-semantic `<div>`, using it in place of a real `<button>` still produces an element assistive technology can't recognize as interactive ā prefer the native element and style it instead.
2camelCase Event Props Don't Change Keyboard Accessibility Requirements
Wiring `onClick` in JSX only handles mouse and touch interaction; a genuinely accessible control still needs the native element or ARIA role plus keyboard event handling (or, more simply, using a real `<button>`) so it can be operated without a mouse.
SEO Implications
- 1
JSX Expressions That Return Nothing Render No Content for Crawlers
If a curly-brace expression evaluates to `null`, `undefined`, or an empty string based on data that isn't available at request time, that section of content is simply absent from the rendered HTML a crawler sees, not just visually hidden.
- 2
Fragments Keep Markup Lean Without Adding Non-Semantic Wrapper Elements
Wrapping sibling elements in `<>...</>` instead of an extra `<div>` avoids introducing meaningless wrapper nodes into the DOM tree, keeping the page's actual semantic structure closer to what search engines parse.
Best Practices
Always Close Every JSX Tag Explicitly
Unlike HTML, JSX has no tolerance for unclosed elements like `<img>` or `<input>` ā every tag needs either a closing tag or a self-closing slash (`<img />`), or the build will fail outright.
Reach for a Fragment Instead of an Extra div
When a component only needs to satisfy JSX's single-root-element rule, wrapping siblings in `<>...</>` avoids polluting the rendered DOM with a wrapper node that has no semantic or styling purpose.
Frequent Bugs
The build fails with a syntax error after adding a second top-level element to a component's return statement.
JSX requires a single root element per component. Wrap the sibling elements in a Fragment (`<>...</>`) or a single container element instead of returning them side by side.
An inline style object written as a plain string is silently ignored or throws an error.
JSX requires inline styles to be a JavaScript object with camelCase property names, passed through the double-brace syntax: `style={{ backgroundColor: 'blue' }}`, not a CSS string like `"background-color: blue"`.
Real-World Examples
Conditionally Rendering JSX Based on Auth State
A navigation bar assigns a different JSX expression to a variable depending on whether a user is logged in, then returns that variable, since JSX blocks can be treated as ordinary JavaScript values.
let greeting;
if (isLoggedIn) {
greeting = <h1>Welcome back!</h1>;
} else {
greeting = <h1>Please log in</h1>;
}
return greeting;