CodeForge

React 19 de Cero a Experto / Fundamentos

JSX: HTML y JavaScript en el mismo idioma

Teoría20 min20 XP

Ya escribiste JSX sin nombrarlo: ese <h1>¡Hola, {nombre}!</h1> que mezcla marcas tipo HTML con JavaScript. JSX es el idioma en el que describes toda UI de React —y aunque se parece a HTML, tiene sus propias reglas—. Hoy lo dominas: cómo insertar expresiones, sus diferencias con HTML, y las trampas que confunden a todos al principio.

Un idioma híbrido

Las llaves: JavaScript dentro del marcado

Todo lo que pongas entre {} en JSX se evalúa como una EXPRESIÓN de JavaScript. Variables, operaciones, llamadas a funciones, ternarios —cualquier cosa que produzca un valor:

Dentro de {} va cualquier EXPRESIÓN (algo que produce un valor): usuario, saldo * 1.19, activo ? ... : ..., gastos[0].toUpperCase(). Lo que NO va son SENTENCIAS como un if o un for (esos no producen un valor) —para condicionales usas ternarios, y para listas usas .map() (próxima lección). La regla: si lo podrías poner a la derecha de un const x =, va entre llaves.

Las diferencias con HTML

JSX se parece a HTML pero tiene reglas propias que hay que conocer:

diferencias.tsx
// 1. 'className' en vez de 'class' (class es palabra reservada en JS)
<div className="tarjeta">...</div>

// 2. camelCase para atributos de varias palabras
<label htmlFor="email">...</label>       // htmlFor, no 'for'
<div onClick={...} tabIndex={0}>...</div> // onClick, tabIndex

// 3. TODOS los tags se cierran (incluso los "vacíos" de HTML)
<img src="foto.jpg" alt="" />             // con la barra final obligatoria
<br />
<input type="text" />

// 4. los estilos en línea son un OBJETO, no un string
<div style={{ color: "red", fontSize: 16 }}>...</div>
//          ↑ doble llave: {} de JSX + {} del objeto; propiedades en camelCase

Las cuatro trampas clásicas: className (no class), camelCase en atributos, cerrar TODOS los tags (<br />, <img />), y estilos como objeto con doble llave. La del style confunde a todos al principio: style={{ ... }} son DOS llaves —las de JSX y las del objeto de JavaScript—, con las propiedades CSS en camelCase (fontSize, no font-size).

Fragmentos: agrupar sin ensuciar

Un componente debe devolver UN solo elemento raíz. Pero a veces quieres devolver varios hermanos sin envolverlos en un <div> extra que ensucia el DOM. Para eso están los fragmentos:

fragmentos.tsx
// ❌ error: dos elementos raíz sueltos
function Malo() {
return (
  <h1>Título</h1>
  <p>Párrafo</p>   // Adjacent JSX elements must be wrapped in an enclosing tag
);
}

// ✅ un fragmento (<>...</>) los agrupa SIN crear un div extra en el DOM:
function Bueno() {
return (
  <>
    <h1>Título</h1>
    <p>Párrafo</p>
  </>
);
}

El fragmento <>...</> (o su forma larga <Fragment>) agrupa varios elementos para cumplir la regla de "una sola raíz", pero sin añadir un <div> real al DOM —tu HTML queda limpio. Es la solución al error "Adjacent JSX elements must be wrapped" que verás a menudo al empezar.

En JSX escribes <div class='tarjeta' style='color: red'>. ¿Qué dos cosas están mal?

Mini-reto

Practica el idioma: 1) en un componente, declara un objeto producto con nombre, precio y enOferta (booleano); 2) muéstralo en JSX usando {} para cada campo, aplicando un descuento con una operación dentro de las llaves si enOferta es true (ternario); 3) dale al contenedor un style en línea (objeto con camelCase) y agrupa dos elementos con un fragmento. Siente cómo lógica y marcado conviven.

Qué sigue

Escribes JSX con soltura. Pero un componente que solo muestra datos fijos es poco útil: su poder está en RECIBIR datos de fuera y adaptarse. La próxima lección introduce las PROPS —cómo un componente acepta datos de quien lo usa— y la composición, la base de construir UIs a partir de piezas reutilizables.