Runnable lesson · press Try it on the examples to edit and run them here.
JSX is a syntax extension for JavaScript that lets you write markup inside your code. It looks like HTML, but it is JavaScript, and it is what makes React components pleasant to write.
A first example
function App() {
return <h1>Hello, JSX!</h1>;
}
The <h1> is not a string and not HTML. It is a JSX element: a description of what React should show.
JSX is not HTML
JSX looks like HTML, but a browser cannot read it. A tool (Babel in the playground, Vite’s plugin in a real project) converts it to normal JavaScript before the browser runs it. Conceptually, the example above becomes:
function App() {
return React.createElement("h1", null, "Hello, JSX!");
}
Modern setups produce a slightly different but equivalent call (jsx("h1", { children: "Hello, JSX!" }) from react/jsx-runtime), so you do not even need to import React in every file. You can read what it produces in JSX Under the Hood. What matters now: every JSX element becomes a JavaScript value, so you can store it in a variable, pass it to a function or return it.
function App() {
const message = <p>Stored in a variable</p>;
return <div>{message}</div>;
}
Why JSX?
You could write React.createElement(...) calls yourself, but nested ones are hard to read. JSX keeps the markup and the logic that belongs to it together, in one place. A button and what happens when you click it live in the same component.
Differences from HTML you must know
JSX is stricter and a little different:
| HTML | JSX |
|---|---|
class="box" | className="box" |
for="email" on a label | htmlFor="email" |
onclick="save()" | onClick={save} (camelCase, a function) |
<br> and <img src="a.png"> | <br /> and <img src="a.png" /> (every tag must be closed) |
style="color: red" | style={{ color: "red" }} (an object) |
tabindex="0" | tabIndex={0} |
JSX also needs one parent element per return, which is the next topic in JSX Syntax and Expressions.
JSX is safe by default
When you put a value inside JSX, React escapes it before putting it in the page. A string such as <script>alert(1)</script> is shown as text, not run. This protects against a common attack, cross-site scripting. The one way around it is called dangerouslySetInnerHTML, and the long name is a warning. See XSS basics in the JavaScript course for the background.
Try breaking it
JSX errors teach you the rules fast. In the playground, remove the closing tag of an element or write class instead of className and read what happens.
function App() {
return <p class="note">Break me</p>;
}
This one still renders, but React prints a warning in the console that class is not valid and className should be used. Warnings like this appear in the console panel under the preview.
Key points
- JSX is JavaScript syntax that looks like HTML; a tool converts it to function calls.
- Use
className,htmlFor, camelCase event names and close every tag. - Values inside JSX are escaped, which protects you from injection.