What is JSX and how does it differ from HTML?
Show answer — try answering out loud first
JSX is a JavaScript syntax extension that lets you write HTML-like markup inside your code. It's not HTML: it's syntactic sugar that the compiler transforms into calls to React functions (like createElement or the JSX runtime), that is, into JavaScript objects.
When you write <h1>Hola</h1> in a component, the browser never sees that. A build tool (Babel, SWC, the TypeScript compiler...) transforms it into a function call that returns an object describing that element. React uses those objects to know what to render.
Key points worth being clear on:
- It's JavaScript, not HTML: that's why you can store it in variables, return it from functions, or pass it as an argument.
- Expressions with curly braces
{}: inside the braces you can put any JavaScript expression (variables, ternaries, function calls). You can't put statements likeiforfordirectly. - Attributes with JavaScript names: since
classandforare reserved words, JSX usesclassNameandhtmlFor. Attributes are written in camelCase (onClick,tabIndex). - A single root element: a JSX expression must return a single node. If you need several siblings without wrapping them in a
<div>, you use a Fragment (<>...</>).
// What you write...
const saludo = <h1 className="titulo">Hola, Mike</h1>;
// ...compiles to something equivalent to this (classic runtime):
// const saludo = React.createElement("h1", { className: "titulo" }, "Hola, Mike");
// That is: JSX produces JavaScript objects, not HTML.
type Props = { nombre: string; esAdmin: boolean };
function TarjetaUsuario({ nombre, esAdmin }: Props) {
// Fragment (<>...</>) to return several siblings without an extra div
return (
<>
{/* The braces evaluate JavaScript expressions */}
<h2>{nombre.toUpperCase()}</h2>
<p>Rol: {esAdmin ? "Administradora" : "Usuaria"}</p>
{/* htmlFor instead of for, className instead of class */}
<label htmlFor="correo" className="etiqueta">Correo</label>
<input id="correo" type="email" />
</>
);
}
// <TarjetaUsuario nombre="Ana" esAdmin={true} /> renders:
// ANA / Rol: Administradora / and the email field with its label.
Trying to return several root elements or using HTML attributes as-is:
// BAD: two root elements and the `class` attribute
function Perfil() {
return (
<h1 class="titulo">Perfil</h1>
<p>Bienvenida</p>
); // Compilation error: JSX must have a single root element
}
// GOOD: Fragment as the root and className instead of class
function PerfilCorregido() {
return (
<>
<h1 className="titulo">Perfil</h1>
<p>Bienvenida</p>
</>
);
}
"JSX is a syntax extension that lets me describe the UI with something similar to HTML, but inside JavaScript. It's really syntactic sugar: the compiler turns it into calls to React functions that return objects. That's why there are differences from HTML, like using
classNameinstead ofclassorhtmlForinstead offor. Inside braces I can evaluate any JavaScript expression, and each JSX block must have a single root element; if I need several siblings, I use a Fragment to avoid adding unnecessary divs."
Fix this component so it compiles and works (it has three JSX-related errors):
function Formulario() {
const titulo = "Registro";
return (
<label for="nombre">titulo</label>
<input id="nombre" class="campo" />
);
}
See solution
function Formulario() {
const titulo = "Registro";
return (
// 1. Fragment: JSX needs a single root element.
// 2. htmlFor and braces to evaluate the variable. 3. className.
<>
<label htmlFor="nombre">{titulo}</label>
<input id="nombre" className="campo" />
</>
);
}