Has escrito ya varios componentes cuyo return contiene algo que parece HTML pero vive dentro de un fichero JavaScript. Eso es JSX, y merece una lección propia porque casi todos los tropiezos de las primeras semanas con React vienen de asumir que JSX es HTML. No lo es: es sintaxis de JavaScript disfrazada de HTML. En esta lección desmitificarás JSX viendo en qué se transforma realmente, aprenderás sus reglas exactas y dominarás la interpolación con llaves, que es lo que convierte una tarjeta de texto fijo en una tarjeta que muestra datos reales de CicloUrbano.
Contenido
- Qué es JSX y en qué se transforma
- Regla 1: un único elemento raíz (y los fragmentos)
- Regla 2: atributos con nombres de JavaScript
- Regla 3: todas las etiquetas deben cerrarse
- Interpolación con llaves: expresiones sí, sentencias no
- Atributos dinámicos
- Estilos en línea con objeto
- Comentarios dentro de JSX
- Qué pinta React y qué no:
null,undefined,falsey el caso del0 - Tabla comparativa HTML vs JSX
- Qué es JSX y en qué se transforma
JSX (JavaScript XML) es una extensión de sintaxis para JavaScript. Los navegadores no la entienden: antes de llegar al navegador, una herramienta de construcción (en nuestro caso Vite, mediante @vitejs/plugin-react) la traduce a JavaScript normal.
La mejor forma de perderle el miedo es ver la traducción. Este componente:
function Bienvenida() {
return (
<header className="cabecera">
<h1>CicloUrbano</h1>
<p>Alquiler de bicicletas por horas</p>
</header>
);
}Se convierte, conceptualmente, en esto:
function Bienvenida() {
return React.createElement(
'header', // 1. tipo de elemento
{ className: 'cabecera' }, // 2. props (atributos)
React.createElement('h1', null, 'CicloUrbano'), // 3. hijos...
React.createElement('p', null, 'Alquiler de bicicletas por horas')
);
}React.createElement recibe siempre tres cosas: el tipo de elemento, un objeto con sus propiedades y sus hijos. Y devuelve un objeto JavaScript sencillo, algo parecido a:
Tres conclusiones importantísimas se derivan de esto:
- JSX es azúcar sintáctico. Podrías escribir React entero sin JSX, con
createElementa mano. Nadie lo hace porque es ilegible, pero conviene saber que no hay magia. - JSX produce objetos, no HTML. Lo que devuelve tu componente no es una cadena de texto ni un nodo del DOM: es un objeto ligero que describe la interfaz. Ese objeto es la pieza que React compara para saber qué actualizar, tema de la próxima lección.
- Un elemento JSX es un valor de JavaScript. Puedes guardarlo en una variable, pasarlo como argumento o devolverlo desde una función:
const encabezado = <h2>Bicicletas disponibles</h2>;
const tarjetas = [<TarjetaBicicleta />, <TarjetaBicicleta />];Nota sobre React 19: desde la «nueva transformación de JSX» (React 17 en adelante) el compilador no genera literalmente
React.createElement, sino una función interna_jsxque importa de forma automática. Ese es el motivo por el que ya no necesitas escribirimport React from 'react'en cada fichero, como sí exigían los tutoriales antiguos. La idea es idéntica; solo cambia el detalle de implementación.
- Regla 1: un único elemento raíz (y los fragmentos)
Una función solo puede devolver un valor. Como JSX se traduce en una llamada a createElement, un componente solo puede devolver un elemento raíz.
// ERROR: dos elementos hermanos al mismo nivel
function Cabecera() {
return (
<h1>CicloUrbano</h1>
<p>Alquiler por horas</p>
);
}Vite lo rechaza con Adjacent JSX elements must be wrapped in an enclosing tag.
La solución obvia es envolver en un contenedor:
function Cabecera() {
return (
<header>
<h1>CicloUrbano</h1>
<p>Alquiler por horas</p>
</header>
);
}Pero a veces no quieres un contenedor extra: añadiría un div inútil al DOM que puede romper un grid, un flex o la semántica de una tabla. Para eso existen los fragmentos, que agrupan sin generar ninguna etiqueta:
function DatosBicicleta() {
return (
<>
<dt>Modelo</dt>
<dd>Urbana Clásica</dd>
<dt>Precio</dt>
<dd>2,50 € / hora</dd>
</>
);
}<>...</> es la sintaxis abreviada del fragmento. Existe también la forma larga, <Fragment>...</Fragment>, necesaria únicamente cuando el fragmento debe llevar una key (algo que ocurre al recorrer listas, en la lección 03-03):
import { Fragment } from 'react';
<Fragment key={bicicleta.id}>
<dt>{bicicleta.modelo}</dt>
<dd>{bicicleta.precioHora} €/h</dd>
</Fragment>Regla práctica: si el contenedor aporta significado (<article>, <section>, <ul>), úsalo. Si solo estaría ahí para contentar a React, usa un fragmento.
- Regla 2: atributos con nombres de JavaScript
En JSX, los atributos son en realidad propiedades de un objeto JavaScript. Eso obliga a dos ajustes respecto al HTML.
Palabras reservadas. class y for son palabras reservadas del lenguaje, así que se renombran:
<article className="tarjeta-bicicleta">
<label htmlFor="modelo">Modelo</label>
<input id="modelo" />
</article>camelCase. Los atributos compuestos por varias palabras se escriben en camelCase, porque así se llaman las propiedades equivalentes en el DOM:
| HTML | JSX |
|---|---|
class |
className |
for |
htmlFor |
tabindex |
tabIndex |
onclick |
onClick |
maxlength |
maxLength |
readonly |
readOnly |
autocomplete |
autoComplete |
colspan |
colSpan |
stroke-width (SVG) |
strokeWidth |
Hay dos excepciones que conviene recordar porque suelen sorprender: los atributos data-* y aria-* mantienen los guiones tal cual, ya que no son propiedades del DOM sino atributos genuinos.
<button
className="boton-reserva"
data-bicicleta-id="bici-001"
aria-label="Reservar Urbana Clásica"
onClick={reservar}
>
Reservar
</button>Buena noticia: si te equivocas, React suele avisarte en la consola con un mensaje muy claro del tipo «Invalid DOM property class. Did you mean className?». Léelos, no los ignores.
- Regla 3: todas las etiquetas deben cerrarse
JSX hereda el rigor de XML: no existen etiquetas abiertas. En HTML puedes escribir <br> o <img src="..."> y el navegador lo tolera; en JSX es un error de sintaxis.
// ERROR
<img src="/logo-ciclourbano.svg" alt="CicloUrbano">
<br>
<input type="text">
// CORRECTO: autocierre con barra final
<img src="/logo-ciclourbano.svg" alt="CicloUrbano" />
<br />
<input type="text" />Lo mismo aplica a tus propios componentes: <TarjetaBicicleta />, no <TarjetaBicicleta>. Y las etiquetas con contenido deben cerrarse siempre y en el orden correcto; JSX no perdona un <p> sin </p> ni un anidamiento cruzado.
- Interpolación con llaves: expresiones sí, sentencias no
Aquí está la potencia real de JSX. Las llaves {} abren una ventana de vuelta a JavaScript: lo que pongas dentro se evalúa y su resultado se inserta en la interfaz.
function TarjetaBicicleta() {
const bicicleta = {
id: 'bici-001',
modelo: 'Urbana Clásica',
tipo: 'urbana',
estado: 'disponible',
precioHora: 2.5
};
const estacion = 'Plaza Mayor';
return (
<article className="tarjeta-bicicleta">
<h3>{bicicleta.modelo}</h3>
<p>Tipo: {bicicleta.tipo}</p>
<p>Estado: {bicicleta.estado}</p>
<p>Estación: {estacion}</p>
<p>{bicicleta.precioHora.toFixed(2)} € / hora</p>
<p>Precio de 3 horas: {(bicicleta.precioHora * 3).toFixed(2)} €</p>
</article>
);
}
export default TarjetaBicicleta;Compara con la versión de la lección anterior: el texto ya no está escrito a mano, sino calculado a partir de datos. Es el mismo componente, pero ahora es dinámico.
Dentro de las llaves cabe cualquier expresión de JavaScript:
<p>{bicicleta.modelo}</p> {/* acceso a propiedad */}
<p>{bicicleta.precioHora * 3}</p> {/* operación aritmética */}
<p>{bicicleta.modelo.toUpperCase()}</p> {/* llamada a método */}
<p>{`${bicicleta.modelo} — ${bicicleta.tipo}`}</p> {/* plantilla de cadena */}
<p>{bicicleta.estado === 'disponible' ? 'Libre' : 'Ocupada'}</p> {/* operador ternario */}
<p>{new Date().getFullYear()}</p> {/* llamada a una API */}La regla que lo gobierna todo: expresiones sí, sentencias no. Una expresión produce un valor; una sentencia ejecuta una acción. Como el contenido de las llaves acaba siendo un argumento de una llamada a función, tiene que producir un valor.
| Permitido (expresión) | No permitido (sentencia) |
|---|---|
bicicleta.modelo |
const x = 5; |
a + b, a * 3 |
if (a) { ... } |
condicion ? 'sí' : 'no' |
for (...) { ... } |
lista.map(...), lista.filter(...) |
switch (...) { ... } |
funcion(argumento) |
return ... |
Esto explica por qué en React el renderizado condicional se escribe con el operador ternario o con &&, y por qué las listas se pintan con .map() en lugar de con un bucle for: son las versiones expresión de esas construcciones. Ambos temas tienen lección propia: Renderizado Condicional y Listas y Claves. Aquí solo necesitas entender el porqué.
Si un cálculo es demasiado largo para caber en una expresión legible, la solución es sacarlo antes del return, donde sí puedes escribir todas las sentencias que quieras:
function TarjetaBicicleta() {
const bicicleta = { modelo: 'Eléctrica Pro', estado: 'alquilada', precioHora: 4 };
// Aquí arriba estás en JavaScript normal: if, for, variables, lo que sea
let etiquetaEstado;
if (bicicleta.estado === 'disponible') {
etiquetaEstado = 'Lista para alquilar';
} else if (bicicleta.estado === 'alquilada') {
etiquetaEstado = 'En uso ahora mismo';
} else {
etiquetaEstado = 'En mantenimiento';
}
return (
<article className="tarjeta-bicicleta">
<h3>{bicicleta.modelo}</h3>
<p>{etiquetaEstado}</p>
</article>
);
}Este patrón —calcular arriba, mostrar abajo— mantiene el JSX limpio y es una de las señales de código React bien escrito.
- Atributos dinámicos
Las llaves también funcionan en los atributos. La diferencia es sutil pero fundamental:
<img src="/logo.svg" /> {/* comillas: valor literal, la cadena "/logo.svg" */}
<img src={rutaLogo} /> {/* llaves: expresión, el valor de la variable rutaLogo */}Un error muy común es mezclar ambas: src="{rutaLogo}" pasa la cadena literal "{rutaLogo}", no el valor. Comillas o llaves, nunca las dos.
Ejemplo completo aplicado a CicloUrbano, construyendo clases CSS dinámicas:
function TarjetaBicicleta() {
const bicicleta = {
id: 'bici-002',
modelo: 'Eléctrica Pro',
tipo: 'electrica',
estado: 'alquilada',
precioHora: 4
};
const disponible = bicicleta.estado === 'disponible';
return (
<article
className={`tarjeta-bicicleta tarjeta-bicicleta--${bicicleta.tipo}`}
data-bicicleta-id={bicicleta.id}
>
<h3>{bicicleta.modelo}</h3>
<span className={`estado estado--${bicicleta.estado}`}>{bicicleta.estado}</span>
<p>{bicicleta.precioHora.toFixed(2)} € / hora</p>
<button disabled={!disponible} aria-label={`Reservar ${bicicleta.modelo}`}>
Reservar
</button>
</article>
);
}Detalles a observar:
classNamecon plantilla de cadena. Produce"tarjeta-bicicleta tarjeta-bicicleta--electrica". Es el patrón habitual para combinar una clase base con un modificador.disabled={!disponible}. Los atributos booleanos reciben un booleano de verdad, no una cadena. Si el valor esfalse, React omite el atributo en el HTML generado. Ojo condisabled="false": como toda cadena no vacía estrueen JavaScript, ¡el botón quedaría deshabilitado!aria-labeldinámico. Los atributos de accesibilidad se benefician muchísimo de la interpolación: cada botón describe exactamente su bicicleta.data-bicicleta-idconserva los guiones, como vimos.
- Estilos en línea con objeto
En HTML, style recibe una cadena de texto CSS. En JSX recibe un objeto de JavaScript:
Ese doble par de llaves confunde a todo el mundo la primera vez, así que sepáralas mentalmente:
- Las llaves exteriores son la interpolación de JSX: «aquí viene una expresión de JavaScript».
- Las llaves interiores son un objeto literal de JavaScript.
Es exactamente lo mismo que escribir:
const estilosDisponible = { color: '#12805c', fontWeight: 'bold' };
<p style={estilosDisponible}>Disponible</p>Reglas de ese objeto:
| CSS | JSX |
|---|---|
background-color: #fff; |
backgroundColor: '#fff' |
font-size: 14px; |
fontSize: 14 (los píxeles se añaden solos) o fontSize: '14px' |
border-radius: 8px; |
borderRadius: 8 |
margin: 0 auto; |
margin: '0 auto' (valores compuestos, siempre en cadena) |
--color-marca: #12805c; |
'--color-marca': '#12805c' (las variables CSS conservan los guiones) |
Las propiedades van en camelCase y los valores son cadenas, salvo los numéricos de propiedades que aceptan píxeles, donde React añade px automáticamente. Cuidado con esa comodidad: lineHeight: 2 significa «2 veces», no «2 píxeles», porque line-height es adimensional.
Ejemplo aplicado, con un color de estado calculado:
function EtiquetaEstado() {
const estado = 'mantenimiento';
const colores = {
disponible: '#12805c',
alquilada: '#b45309',
mantenimiento: '#9b1c1c'
};
return (
<span
style={{
color: colores[estado],
border: `1px solid ${colores[estado]}`,
borderRadius: 4,
padding: '0.15rem 0.5rem',
fontSize: 13,
textTransform: 'uppercase'
}}
>
{estado}
</span>
);
}Cuándo usar estilos en línea: solo para valores realmente dinámicos que dependen de datos (un color calculado, un ancho de barra de progreso). Para todo lo demás, hojas de estilo: los estilos en línea no admiten :hover, ni media queries, ni pseudoelementos, y no se cachean. Las estrategias completas de estilado se ven en Estilos en los Componentes.
- Comentarios dentro de JSX
Los comentarios // y /* */ de JavaScript no funcionan dentro del JSX: acabarían pintados como texto. Hay que envolverlos en llaves:
function TarjetaBicicleta() {
// Este comentario sí es válido: estamos en JavaScript normal
const bicicleta = { modelo: 'Carga Max', precioHora: 5.5 };
return (
<article className="tarjeta-bicicleta">
{/* Este es el comentario válido dentro de JSX */}
<h3>{bicicleta.modelo}</h3>
{/*
Los comentarios de varias líneas
también funcionan así
*/}
<p>{bicicleta.precioHora.toFixed(2)} € / hora</p>
{/* <p>Esta línea está desactivada temporalmente</p> */}
</article>
);
}En los atributos, en cambio, se comenta como en JavaScript, porque ahí ya estás dentro de una expresión:
La mayoría de editores hacen lo correcto automáticamente con Ctrl+/ si tienen soporte de JSX.
- Qué pinta React y qué no:
null, undefined, false y el caso del 0
null, undefined, false y el caso del 0React ignora silenciosamente ciertos valores dentro de las llaves. Saber cuáles evita sorpresas desagradables.
| Valor | ¿Se pinta? | Resultado en pantalla |
|---|---|---|
'Urbana Clásica' |
Sí | Urbana Clásica |
2.5 |
Sí | 2.5 |
0 |
Sí | 0 |
null |
No | nada |
undefined |
No | nada |
true / false |
No | nada |
['a', 'b'] |
Sí | ab (concatena los elementos) |
{ modelo: 'X' } |
Error | Objects are not valid as a React child |
Que null, undefined y false no se pinten es una funcionalidad muy útil: permite escribir «pinta esto solo si se cumple algo» sin ninguna estructura especial.
const bicicleta = { modelo: 'Eléctrica Pro', estado: 'disponible', autonomiaKm: 45 };
<article className="tarjeta-bicicleta">
<h3>{bicicleta.modelo}</h3>
{/* Si autonomiaKm es undefined, no se pinta nada: sin errores ni huecos raros */}
<p>{bicicleta.autonomiaKm && `Autonomía: ${bicicleta.autonomiaKm} km`}</p>
</article>Y aquí está la trampa del 0. El operador && devuelve el operando de la izquierda cuando este es falsy. Si ese operando es 0, React sí lo pinta, porque 0 es un número perfectamente válido:
const estacion = { nombre: 'Parque Norte', plazasLibres: 0 };
// MAL: cuando plazasLibres vale 0, en pantalla aparece un "0" suelto
<p>{estacion.plazasLibres && `${estacion.plazasLibres} plazas libres`}</p>
// -> pinta: 0
// BIEN: comparación explícita, la condición ya es un booleano
<p>{estacion.plazasLibres > 0 && `${estacion.plazasLibres} plazas libres`}</p>
// -> no pinta nada
// TAMBIÉN BIEN: ternario, que deja explícito el caso contrario
<p>{estacion.plazasLibres > 0 ? `${estacion.plazasLibres} plazas libres` : 'Estación llena'}</p>Este «cero fantasma» es uno de los fallos más reportados por principiantes en React. La regla para evitarlo: la izquierda de && debe ser siempre un booleano, no un número ni una cadena.
Sobre el error de los objetos: {bicicleta} falla porque React no sabe cómo pintar un objeto. Debes acceder a sus propiedades ({bicicleta.modelo}) o, si estás depurando, convertirlo en texto:
- Tabla comparativa HTML vs JSX
| Aspecto | HTML | JSX |
|---|---|---|
| Clase CSS | class="tarjeta" |
className="tarjeta" |
| Etiqueta de formulario | for="modelo" |
htmlFor="modelo" |
| Eventos | onclick="reservar()" |
onClick={reservar} (referencia, sin paréntesis) |
| Atributos compuestos | tabindex, maxlength |
tabIndex, maxLength |
data-* y aria-* |
data-id, aria-label |
Igual, con guiones |
| Etiquetas vacías | <br>, <img src="..."> |
<br />, <img src="..." /> |
| Estilo en línea | style="color: red" |
style={{ color: 'red' }} |
| Valores dinámicos | No existen | {expresion} |
| Comentarios | <!-- ... --> |
{/* ... */} |
| Elemento raíz | Varios permitidos | Uno solo (o un fragmento <>...</>) |
| Booleanos | disabled |
disabled={true} o simplemente disabled |
| Mayúsculas | Irrelevantes | Determinan si es etiqueta HTML o componente |
Errores Comunes y Consejos
- Escribir
classen vez declassName. El aviso aparece en la consola y los estilos no se aplican. Es tan frecuente que conviene automatizarlo: con ESLint bien configurado te lo marca al escribir. - Mezclar comillas y llaves:
src="{ruta}". Pasa la cadena literal. O comillas para valores fijos, o llaves para expresiones. - Intentar meter un
ifo unfordentro de las llaves. Son sentencias. Sácalos antes delreturno usa sus equivalentes en forma de expresión (? :,&&,.map()). - Olvidar el autocierre en
<br>,<img>,<input>o<hr>. Error de sintaxis inmediato; el mensaje de Vite señala la línea con precisión. - El «cero fantasma» con
&&. Repítelo hasta que se te quede: la izquierda del&&debe ser un booleano.plazasLibres > 0 && ..., nuncaplazasLibres && .... - Pintar un objeto:
{bicicleta}en vez de{bicicleta.modelo}. El mensajeObjects are not valid as a React childes literal y te dice exactamente qué pasa. - Un solo par de llaves en
style.style={{ color: 'red' }}lleva dos: interpolación más objeto. - Consejo: cuando dudes de qué hace un JSX complicado, tradúcelo mentalmente a
createElement. Si la traducción no tiene sentido como llamada a función, el JSX tampoco lo tendrá. - Consejo: si el JSX de un componente ocupa más de una pantalla, no es un problema de JSX sino de diseño: seguramente ese componente esté haciendo demasiadas cosas y deba dividirse. Lo trabajarás en el Módulo 2.
Ejercicios
Ejercicio 1
Traduce a JSX correcto el siguiente HTML de una tarjeta de estación de CicloUrbano. Debe ser un componente TarjetaEstacion completo, listo para usarse, con las tres correcciones de sintaxis que hacen falta.
<div class="tarjeta-estacion" style="border-left: 4px solid #12805c">
<h3>Estación Central</h3>
<p>Barrio Ensanche</p>
<hr>
<label for="plazas">Plazas totales</label>
<input id="plazas" type="number" value="30" readonly>
</div>Ejercicio 2
Escribe un componente ResumenReserva que, a partir de estas constantes declaradas dentro del componente, muestre el modelo, las horas, el precio total con dos decimales y un aviso solo cuando la reserva supere las 4 horas. Todo debe salir de expresiones interpoladas, sin texto fijo duplicado.
const bicicleta = { modelo: 'Eléctrica Pro', precioHora: 4 };
const reserva = { usuario: 'Ana Ribera', horas: 6, estado: 'activa' };Ejercicio 3
El siguiente componente tiene un fallo visual: cuando plazasLibres vale 0, aparece un 0 suelto en pantalla en lugar de no mostrarse nada. Explica exactamente por qué ocurre y propón dos soluciones distintas.
function DisponibilidadEstacion() {
const estacion = { nombre: 'Plaza Mayor', plazasLibres: 0 };
return (
<div>
<h3>{estacion.nombre}</h3>
{estacion.plazasLibres && <p>Quedan {estacion.plazasLibres} plazas</p>}
</div>
);
}Soluciones
Solución 1.
// src/componentes/TarjetaEstacion.jsx
function TarjetaEstacion() {
return (
<div className="tarjeta-estacion" style={{ borderLeft: '4px solid #12805c' }}>
<h3>Estación Central</h3>
<p>Barrio Ensanche</p>
<hr />
<label htmlFor="plazas">Plazas totales</label>
<input id="plazas" type="number" value="30" readOnly />
</div>
);
}
export default TarjetaEstacion;Las correcciones: class → className; el style como cadena → objeto con borderLeft en camelCase y el valor compuesto entre comillas; <hr> → <hr /> y el <input> autocerrado; for → htmlFor; readonly → readOnly.
Un detalle extra: React avisará en consola de que un input con value fijo y sin manejador de cambios es de solo lectura. Aquí es intencionado, y por eso lleva readOnly; los campos editables se estudian en Formularios y Componentes Controlados.
Solución 2.
// src/componentes/ResumenReserva.jsx
function ResumenReserva() {
const bicicleta = { modelo: 'Eléctrica Pro', precioHora: 4 };
const reserva = { usuario: 'Ana Ribera', horas: 6, estado: 'activa' };
// Cálculo fuera del JSX: más legible y reutilizable
const total = bicicleta.precioHora * reserva.horas;
return (
<article className="resumen-reserva">
<h3>Reserva de {reserva.usuario}</h3>
<p>
{bicicleta.modelo} · {reserva.horas} horas
</p>
<p>
Total: <strong>{total.toFixed(2)} €</strong>
</p>
{reserva.horas > 4 && <p>Reserva de larga duración: recuerda devolverla en su estación.</p>}
</article>
);
}
export default ResumenReserva;Con estos datos muestra «Total: 24.00 €» y el aviso, porque 6 es mayor que 4. Fíjate en que la condición del && es una comparación, así que ya es un booleano: no hay riesgo de cero fantasma.
Solución 3.
Por qué ocurre: el operador && evalúa el operando izquierdo; si es falsy, devuelve ese mismo valor en lugar de un booleano. Como plazasLibres vale 0, la expresión completa devuelve 0. Y 0 es un número válido para React, que lo pinta tal cual. Solo null, undefined, true y false se omiten silenciosamente.
Solución A — convertir la condición en un booleano explícito:
Solución B — usar un ternario, que además cubre el caso contrario:
{estacion.plazasLibres > 0 ? (
<p>Quedan {estacion.plazasLibres} plazas</p>
) : (
<p>Estación completa</p>
)}Una tercera vía, algo menos legible pero también válida, es forzar el booleano con doble negación: {!!estacion.plazasLibres && ...}. Prefiere siempre la comparación explícita: comunica mejor la intención.
Conclusión
JSX no es HTML: es sintaxis que se transforma en llamadas a función que producen objetos JavaScript describiendo la interfaz. De esa naturaleza se derivan todas sus reglas: un único elemento raíz (o un fragmento <>...</>), atributos con nombres de propiedad del DOM (className, htmlFor, camelCase), cierre obligatorio de todas las etiquetas, y llaves {} para interpolar expresiones —nunca sentencias—. Sabes construir atributos dinámicos, aplicar estilos en línea con objeto, comentar con {/* */} y evitar la trampa del 0 con &&.
Con eso ya puedes describir cualquier interfaz. Queda una pregunta esencial por responder: ¿qué hace React exactamente con esos objetos que devuelven tus componentes? ¿Cómo pasa de una descripción en memoria a píxeles en la pantalla, y cómo consigue actualizarla sin repintarlo todo? Eso es lo que verás en Cómo Renderiza React: Virtual DOM y Reconciliación, la lección que cierra este primer módulo.
Curso de React
Módulo 1: Introducción a React
- ¿Qué es React?
- Configuración del Entorno de Desarrollo
- Hola Mundo en React
- JSX: Extensión de Sintaxis de JavaScript
- Cómo Renderiza React: Virtual DOM y Reconciliación
Módulo 2: Componentes de React
- Entendiendo los Componentes
- Componentes Funcionales vs de Clase
- Props: Pasando Datos a Componentes
- State: Gestión del Estado del Componente
- Estilos en los Componentes: CSS, Módulos y Utilidades
Módulo 3: Trabajando con Eventos
- Manejo de Eventos en React
- Renderizado Condicional
- Listas y Claves
- Formularios y Componentes Controlados
- Validación de Formularios y Componentes No Controlados
- Accesibilidad en Componentes Interactivos
Módulo 4: Conceptos Avanzados de Componentes
- Elevando el Estado
- Composición vs Herencia
- Métodos del Ciclo de Vida de React
- Hooks: Introducción y Uso Básico
- Límites de Error: Capturar Fallos en la Interfaz
Módulo 5: Hooks de React
- Hook useState
- Hook useEffect
- Hook useRef y Acceso al DOM
- Hook useContext
- Hook useReducer
- Hooks Personalizados
Módulo 6: Enrutamiento en React
- Introducción a React Router
- Configuración de React Router
- Rutas Anidadas
- Navegación Programática
- Rutas Protegidas y Control de Acceso
Módulo 7: Gestión del Estado
- Introducción a la Gestión del Estado
- API de Contexto
- Redux: Introducción y Configuración
- Redux: Acciones y Reductores
- Redux: Conectando a React
- Estado del Servidor: Peticiones, Caché y Sincronización
Módulo 8: Optimización del Rendimiento
- Técnicas de Optimización del Rendimiento en React
- Memorización con React.memo
- Hooks useMemo y useCallback
- División de Código y Carga Perezosa
- Medir el Rendimiento con React DevTools Profiler
Módulo 9: Pruebas en React
- Introducción a las Pruebas
- Pruebas Unitarias con Jest
- Pruebas de Componentes con React Testing Library
- Pruebas de Código Asíncrono y Simulación de APIs
- Pruebas de Extremo a Extremo con Cypress
Módulo 10: Temas Avanzados
- Renderizado del Lado del Servidor (SSR) con Next.js
- Generación de Sitios Estáticos (SSG) con Next.js
- Suspense y React Server Components
- TypeScript con React
- React Native: Creación de Aplicaciones Móviles
