React JSX se parece al HTML: se compila a JavaScript.
JSX es un marcado de JavaScript: una raíz única, etiquetas cerradas, atributos en camelCase y llaves para las expresiones, con las reglas clásicas que los principiantes se encuentran primero.
JSX se parece al HTML en un archivo de componentes, pero se compila a JavaScript; ese hecho explica casi todas las reglas sintácticas.
En capítulos anteriores se solía tratar el marcado que devuelve un componente —por ejemplo <h1>Hello</h1>— como un “markup” informal. El nombre real es JSX. El objetivo aquí es sencillo: tratar a JSX como JavaScript que casualmente se parece al HTML. Una vez que esto queda claro, la mayoría de las reglas sintácticas superficiales dejan de parecer arbitrarias.
¿Por qué JSX? Marcado y lógica juntos
En el desarrollo front-end clásico, la estructura se mantenía en archivos HTML y el comportamiento en archivos JavaScript. En la práctica, resulta difícil separar el aspecto visual de un botón de su manejo al hacer clic en él. React mantiene ambos elementos dentro de una misma unidad: el componente; por eso necesita una forma de escribir marcado dentro del JavaScript. Esa sintaxis es JSX.
Visualmente es similar a HTML. Dado que el compilador convierte JSX en JavaScript, las reglas son más estrictas que las de HTML. Comience con las tres reglas que afectan primero a los principiantes.
Las tres reglas de JSX
Regla 1: un único nodo raíz
Un componente solo puede devolver un árbol JSX. Varios elementos hermanos deben encontrarse bajo un único padre.
// 🔴 two siblings side by side — error
return (
<h1>Title</h1>
<p>Content</p>
);
// ✅ wrapped in one
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
Si un <div> adicional complicaría el DOM, envuelva a los elementos hermanos en un Fragmento (<>...</>).
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
¿Por qué un único nodo raíz? JSX se convierte en un valor de JavaScript. Una función no puede devolver dos valores al mismo tiempo sin empaquetarlos; la misma lógica aplica a JSX. El hecho de que “esto es JavaScript, no HTML” hace que esta regla tenga sentido.
Regla 2: cerrar todas las etiquetas
HTML permite ciertas etiquetas como <img> o <br> sin etiqueta de cierre. En JSX, toda etiqueta debe cerrarse. Las etiquetas sin hijos utilizan la forma de cierre automático />.
// 🔴 an HTML habit — error
<img src="logo.png">
<input type="text">
// ✅ self-closing
<img src="logo.png" />
<input type="text" />
Regla 3: atributos en formato camelCase
Los atributos de JSX se convierten en claves de un objeto JavaScript, por lo que sus nombres siguen las convenciones de JavaScript (camelCase), y no los nombres propios de HTML. Constantemente surgen colisiones con palabras reservadas:
class→className(classes una palabra reservada en JavaScript)for→htmlFor(fortambién es una palabra reservada)
// 🔴 straight from HTML
<div class="card">
<label for="email">Email</label>
</div>
// ✅ the JSX way
<div className="card">
<label htmlFor="email">Email</label>
</div>
Esa misma asignación convierte onclick en onClick y tabindex en tabIndex. No es necesario memorizar la lista completa: el completado del editor y TypeScript corrigen rápidamente los nombres incorrectos.
Paréntesis curvos {} — JavaScript dentro de JSX
Aquí es donde JSX deja de ser un template estático. Dado que JSX es JavaScript, los paréntesis curvos {} permiten incluir un valor de JavaScript en su lugar. HTML solo puede contener texto fijo; JSX, en cambio, puede evaluar expresiones.
function Greeting() {
const name = 'Jane';
return <h1>Hello, {name}!</h1>; // inside the braces is JavaScript
}
{name} se reemplaza por el valor de name ('Jane'). Los paréntesis aceptan cualquier expresión — código que evalúa a un valor — y no solo variables simples.
function Bill() {
const price = 12000;
const count = 3;
return (
<div>
<p>Unit price: {price} won</p>
<p>Quantity: {count}</p>
<p>Total: {price * count} won</p> {/* arithmetic works too */}
<p>{new Date().getFullYear()} receipt</p> {/* function calls work too */}
</div>
);
}
Los paréntesis también se utilizan en valores de atributos. En ese caso, se omiten las comillas alrededor de los paréntesis.
function Avatar() {
const user = { name: 'Jane Kim', imageUrl: '/me.png' };
return <img src={user.imageUrl} alt={user.name} />;
}
src="..."— las comillas indican una cadena literal.src={...}— los corchetes indican un valor de JavaScript.
Solo se permiten expresiones
Dentro de los corchetes puede colocarse una expresión que genere un valor. No se pueden incluir instrucciones como if, for o const.
// 🔴 an if statement isn't an expression, so this fails
<p>{if (count > 0) 'in stock'}</p>
// ✅ the ternary operator is an expression, so it works
<p>{count > 0 ? 'in stock' : 'out of stock'}</p>
La interfaz de usuario condicional con operadores ternarios, && y patrones relacionados pertenece a un capítulo dedicado al renderizado condicional. Por ahora, la regla de funcionamiento es: solo el código que genera valores debe ir dentro de los corchetes.
Doble par de corchetes {{ }} — un objeto dentro de los corchetes
El patrón {{ }} que aparece con frecuencia en JSX no es una característica distinta del lenguaje. Se trata de un objeto JavaScript { } anidado dentro de los corchetes de incrustación externos. Los estilos en línea son el ejemplo típico.
// outer { } = "I'm putting JavaScript here"
// inner { } = the object itself
<div style={{ color: 'tomato', fontSize: 20 }}>styled</div>
HTML utilizaría una cadena como style="color: tomato". JSX, en cambio, pasa un objeto, por lo que los nombres de las propiedades están en formato camelCase (fontSize en lugar de font-size) y los valores suelen ser cadenas o números. Si los corchetes dobles parecen poco claros, divídalos primero en una variable con nombre.
const cardStyle = { color: 'tomato', fontSize: 20 };
<div style={cardStyle}>styled</div> // exactly the same as above
El corchete externo significa “insertar un valor de JavaScript aquí”; el objeto interno es ese valor.
Cómo escribir comentarios
Los comentarios dentro de JSX también utilizan corchetes: un comentario en bloque de JavaScript envuelto en {}.
return (
<div>
{/* this is a comment inside JSX */}
<h1>Title</h1>
</div>
);
Juntándolo todo
Las reglas anteriores caben en un componente de tarjeta de producto.
// src/ProductCard.tsx
function ProductCard() {
const product = {
name: 'Mechanical Keyboard',
price: 89000,
inStock: true,
imageUrl: "https://picsum.photos/200/300",
};
return (
<div className="card" style={{ padding: 16 }}>
{/* image: self-closing + brace attributes */}
<img src={product.imageUrl} alt={product.name} />
<h2>{product.name}</h2>
<p>Price: {product.price.toLocaleString()} won</p>
{/* show stock with an expression (ternary) — more in the next chapter */}
<p>{product.inStock ? 'In stock' : 'Out of stock'}</p>
</div>
);
}
export default ProductCard;
Ese ejemplo utiliza las tres reglas estructurales (raíz única, etiquetas cerradas, className) y todos los patrones comunes de llaves (interpolación de texto, atributos, operaciones aritméticas, condicionales, objeto de estilo).
Conclusión
- JSX es JavaScript, no HTML — por eso su sintaxis es más estricta que la de HTML.
- Tres reglas estructurales: agrupar elementos hermanos bajo una única raíz (un Fragmento es suficiente), cerrar todas las etiquetas y utilizar atributos en formato camelCase (
class→className,for→htmlFor). - Las llaves
{}contienen una expresión de JavaScript, ya sea en texto o en atributos. - Solo las expresiones que generan un valor deben ir entre llaves; no las instrucciones como
ifofor.
{{ }} no es una sintaxis nueva; se trata de un objeto dentro de llaves. Los estilos en línea son el caso clásico.El siguiente paso lógico es introducir datos en el componente desde el exterior, a través de props. Codificar manualmente un objeto product dentro del componente funciona para una demostración; con props, la misma ProductCard puede mostrar muchos productos, y ahí es donde los tipos de TypeScript cobran mayor importancia.
Referencias
- Documentación de React sobre marcado con JSX
- Documentación de React sobre incrustación de expresiones
Lecturas relacionadas
- Errores comunes de TypeScript en React y cómo resolverlos — Una guía práctica sobre cinco categorías recurrentes de errores en TypeScript en aplicaciones React: props, eventos, estado, datos asíncronos e hijos, con soluciones claras para cada uno.
- Reducir el grado de complejidad de las componentes React y los componentes God — Aprenda siete patrones concretos de refactorización para descomponer componentes React excesivamente grandes, aislando el estado, la obtención de datos, los permisos y la lógica de carga en lugar de simplemente dividir archivos.