Ya sabes que tus componentes devuelven objetos JavaScript que describen la interfaz. Falta la pieza que cierra el círculo: qué hace React con esos objetos para convertirlos en píxeles y, sobre todo, cómo consigue actualizar la pantalla cuando los datos cambian sin volver a construirlo todo. Entender este mecanismo no es un lujo teórico: explica por qué las listas necesitan key, por qué a veces un componente pierde misteriosamente lo que el usuario había escrito y por qué «un render» no significa «tocar el DOM». Es el conocimiento que separa a quien usa React de quien lo entiende.
Contenido
- Dos árboles: el DOM real y el árbol de elementos de React
- Por qué crear objetos es barato y tocar el DOM es caro
- Las tres fases: disparo, reconciliación y commit
- Las heurísticas del algoritmo de diferencias
- Mismo tipo de elemento: se actualiza
- Distinto tipo: se destruye y se recrea (y el estado se pierde)
- Las listas necesitan una identidad estable
- Render, commit y repintado del navegador
- Un render no siempre toca el DOM
- Dos árboles: el DOM real y el árbol de elementos de React
Cuando el navegador carga una página, construye el DOM (Document Object Model): un árbol de objetos que representa cada etiqueta. Esos objetos son pesados. Un solo <div> del DOM tiene cientos de propiedades y métodos: geometría, estilos calculados, eventos, accesibilidad, relaciones con sus vecinos.
Lo que devuelven tus componentes es otra cosa completamente distinta:
// Esto que escribes...
<article className="tarjeta-bicicleta">
<h3>Urbana Clásica</h3>
<p>2,50 € / hora</p>
</article>// ...se convierte en un objeto JavaScript minúsculo, algo así:
{
type: 'article',
props: {
className: 'tarjeta-bicicleta',
children: [
{ type: 'h3', props: { children: 'Urbana Clásica' } },
{ type: 'p', props: { children: '2,50 € / hora' } }
]
}
}Ese objeto es un elemento de React. No es un nodo del DOM: no tiene métodos, no está en la pantalla, no ocupa espacio, no sabe nada de píxeles. Es una descripción, una receta. Y como es solo datos, crearlo cuesta prácticamente nada.
Al árbol completo de esos objetos que React mantiene en memoria se le llama históricamente Virtual DOM. El nombre es algo desafortunado —no es un DOM ni es virtual— pero está tan asentado que lo usaremos igual. Lo importante es el concepto: React mantiene en memoria una copia ligera de cómo debe verse la interfaz, y la usa para decidir qué cambiar en el DOM real.
flowchart LR
subgraph M[En memoria: barato]
A[Árbol de elementos<br/>objetos JS ligeros]
end
subgraph N[En el navegador: caro]
B[DOM real<br/>nodos pesados]
end
A -- "React aplica solo las diferencias" --> B
- Por qué crear objetos es barato y tocar el DOM es caro
La estrategia entera de React se apoya en una asimetría de coste.
Crear objetos JavaScript es baratísimo. Reservar memoria para unos cuantos objetos planos es una de las operaciones más rápidas que hace un motor de JavaScript. Construir un árbol de elementos para cien tarjetas de bicicleta cuesta una fracción de milisegundo.
Modificar el DOM es caro, y no por la escritura en sí, sino por lo que desencadena:
| Operación | Qué provoca en el navegador |
|---|---|
| Cambiar un texto | Repintado de esa zona |
Cambiar color o background |
Repintado (paint) |
| Cambiar tamaño, posición o insertar un nodo | Reflow: recalcular la geometría de toda la página |
Leer offsetHeight justo tras escribir |
Fuerza un reflow síncrono e inmediato |
El reflow es lo verdaderamente costoso: el navegador debe recalcular dónde va cada elemento de la página. Hacerlo cien veces seguidas en un bucle es la receta clásica de una interfaz que se atasca.
Por eso React prefiere pensar mucho en memoria para tocar poco el DOM. Compara dos formas de actualizar el estado de una bicicleta en una lista de cincuenta:
// Enfoque ingenuo con DOM directo: destruir y reconstruir todo
contenedor.innerHTML = ''; // 50 nodos destruidos
bicicletas.forEach((b) => construirTarjeta(b)); // 50 nodos creados + 50 inserciones
// Resultado: reflow masivo, se pierde el foco y el scroll// Enfoque de React: // 1. Construye 50 objetos ligeros en memoria (microsegundos) // 2. Los compara con los 50 anteriores (microsegundos) // 3. Detecta que solo cambió un texto // 4. Ejecuta UNA operación: nodoTexto.data = 'alquilada' // Resultado: repintado mínimo, foco y scroll intactos
Un matiz honesto e importante: el Virtual DOM no es magia ni es intrínsecamente más rápido que un código imperativo perfectamente optimizado escrito a mano. Un experto que actualice exactamente el nodo necesario siempre ganará en una micro-comparación. Lo que aporta React es que ese resultado casi óptimo lo obtienes por defecto, sin pensarlo, y de forma sostenible cuando la aplicación crece. Cambias un poco de rendimiento teórico por muchísima previsibilidad y mantenibilidad.
- Las tres fases: disparo, reconciliación y commit
Cada actualización de la interfaz recorre siempre las mismas tres fases.
flowchart TD
A["1. DISPARO<br/>Render inicial o cambio de estado"] --> B["2. RENDER + RECONCILIACIÓN<br/>React ejecuta los componentes y compara<br/>el árbol nuevo con el anterior"]
B --> C{"¿Hay diferencias?"}
C -- No --> D["Fin: el DOM no se toca"]
C -- Sí --> E["3. COMMIT<br/>React aplica al DOM real<br/>solo las diferencias detectadas"]
E --> F["El navegador repinta la zona afectada"]
Fase 1: el disparo
Solo hay dos motivos por los que React renderiza:
- El render inicial, cuando llamas a
createRoot(...).render(<App />). Ocurre una sola vez. - Un cambio de estado, cuando un componente actualiza su estado con la función que le da
useState. Esto lo estudiarás en State: Gestión del Estado del Componente.
Es una lista muy corta y conviene memorizarla, porque delimita todo lo que puede hacer que la pantalla cambie.
Fase 2: render y reconciliación
React ejecuta tus funciones de componente. Eso es literalmente lo que significa «renderizar»: llamar a App(), que devuelve elementos, algunos de los cuales son componentes, que React también llama, recursivamente, hasta tener el árbol completo.
Con el árbol nuevo en la mano, lo compara con el que ya tenía. A ese proceso de comparación se le llama reconciliación o diffing, y su resultado es una lista de operaciones concretas: «cambiar este texto», «añadir esta clase», «insertar este nodo», «eliminar aquel».
Una consecuencia fundamental: renderizar no toca el DOM. La fase de render es un cálculo puro en memoria. Por eso tus componentes deben ser funciones puras: dados los mismos datos, deben devolver siempre el mismo resultado, sin efectos secundarios. React se reserva el derecho a ejecutarlos las veces que necesite (recuerda StrictMode, que los ejecuta dos veces en desarrollo precisamente para descubrir impurezas).
Fase 3: el commit
React aplica al DOM real la lista de operaciones calculada, y solo esa. Si únicamente cambió un texto, ejecuta una sola instrucción. Si no cambió nada, no toca el DOM en absoluto.
Todas las modificaciones se aplican de forma síncrona y agrupada, para que el usuario nunca vea un estado intermedio inconsistente.
- Las heurísticas del algoritmo de diferencias
Comparar dos árboles cualesquiera y encontrar el mínimo número de cambios es un problema de coste O(n³): para mil elementos serían mil millones de comparaciones, inviable a 60 fotogramas por segundo.
React lo resuelve renunciando a la perfección y adoptando dos suposiciones que son casi siempre ciertas en interfaces reales. Con ellas el coste baja a O(n), lineal:
- Dos elementos de tipo distinto producen árboles distintos. Si donde había un
<article>ahora hay un<section>, React no intenta reaprovechar nada: destruye y recrea. - El desarrollador puede indicar qué hijos son estables entre renders mediante la prop
key.
React tampoco compara nunca elementos de niveles distintos del árbol: recorre ambos árboles en paralelo, nivel a nivel, comparando posición con posición. Si un nodo se mueve de nivel, para React es un nodo distinto.
Estas heurísticas no son un detalle interno: son las reglas que debes conocer para escribir componentes que se comporten bien. Los dos apartados siguientes desarrollan la primera; el séptimo, la segunda.
- Mismo tipo de elemento: se actualiza
Si el elemento en la misma posición conserva su tipo, React mantiene el nodo del DOM y solo actualiza los atributos que hayan cambiado.
// Render anterior
<article className="tarjeta-bicicleta">
<h3>Urbana Clásica</h3>
<p>disponible</p>
</article>
// Render nuevo
<article className="tarjeta-bicicleta tarjeta-bicicleta--destacada">
<h3>Urbana Clásica</h3>
<p>alquilada</p>
</article>React compara y decide:
| Elemento | Comparación | Acción |
|---|---|---|
<article> |
Mismo tipo | Conserva el nodo; actualiza className |
<h3> |
Mismo tipo, mismo contenido | No hace nada |
<p> |
Mismo tipo, texto distinto | Conserva el nodo; actualiza solo el texto |
Dos operaciones en total. El nodo <article> es el mismo objeto del DOM que antes: no se ha creado ninguno nuevo. Esto tiene consecuencias muy visibles:
- Si el usuario tenía el foco en un campo dentro de esa tarjeta, lo conserva.
- Si había una animación CSS en curso, continúa.
- Si había un
<input>con texto escrito por el usuario, el texto sigue ahí.
La misma lógica se aplica a tus componentes: si en una posición había un <TarjetaBicicleta /> y sigue habiendo un <TarjetaBicicleta />, React considera que es el mismo componente, conserva su estado interno y simplemente lo vuelve a ejecutar con los datos nuevos.
- Distinto tipo: se destruye y se recrea (y el estado se pierde)
Cuando el tipo cambia, React aplica la primera heurística sin contemplaciones: destruye el subárbol entero y lo construye de cero.
// Render anterior
<article className="tarjeta">
<FormularioReserva />
</article>
// Render nuevo: article -> section
<section className="tarjeta">
<FormularioReserva />
</section>Aunque el contenido interior sea idéntico, React elimina el <article> con todo lo que cuelga de él y crea un <section> nuevo. El FormularioReserva se desmonta y se vuelve a montar desde cero: pierde todo su estado interno. Si el usuario había escrito su nombre y las horas de la reserva, esos datos desaparecen.
Esto explica un fallo desconcertante y muy real. Observa:
// PROBLEMÁTICO: el tipo del contenedor cambia según el estado
function PanelReserva() {
const [modoCompacto, setModoCompacto] = useState(false);
if (modoCompacto) {
return (
<div className="panel-compacto">
<FormularioReserva />
</div>
);
}
return (
<section className="panel-amplio">
<FormularioReserva />
</section>
);
}Cada vez que el usuario alterna entre modo compacto y amplio, el contenedor pasa de div a section: distinto tipo, subárbol destruido, formulario vaciado. El usuario percibe que «la aplicación borra lo que escribo al cambiar de vista» y el motivo real está a dos niveles de distancia del formulario.
La corrección es mantener el mismo tipo de elemento y variar solo lo que de verdad cambia:
// CORRECTO: mismo tipo siempre, solo cambia la clase
function PanelReserva() {
const [modoCompacto, setModoCompacto] = useState(false);
return (
<section className={modoCompacto ? 'panel-compacto' : 'panel-amplio'}>
<FormularioReserva />
</section>
);
}Ahora React reconoce el mismo <section> en la misma posición, actualiza únicamente className y el formulario conserva intacto lo que el usuario había escrito.
Resumen operativo:
| Situación | Decisión de React | Efecto sobre el estado |
|---|---|---|
Mismo tipo (div → div) |
Reutiliza el nodo, actualiza props | Se conserva |
Mismo componente (<Tarjeta /> → <Tarjeta />) |
Reutiliza la instancia, la vuelve a ejecutar | Se conserva |
Distinto tipo (div → section) |
Destruye y recrea el subárbol | Se pierde |
Distinto componente (<Tarjeta /> → <Fila />) |
Destruye y recrea | Se pierde |
| Elemento eliminado del árbol | Desmonta | Se pierde |
La idea que subyace: para React, la identidad de un componente es «su tipo en su posición dentro del árbol». Cambia cualquiera de las dos cosas y, a sus ojos, es otro componente distinto.
- Las listas necesitan una identidad estable
Esa definición de identidad —tipo más posición— funciona bien para estructuras fijas, pero se rompe con las listas. Imagina el catálogo de CicloUrbano:
Render anterior: Render nuevo (se añade una bicicleta al principio):
0: Urbana Clásica 0: Eléctrica Pro <- nueva
1: Eléctrica Pro 1: Urbana Clásica
2: Carga Max 2: Eléctrica Pro
3: Carga MaxComparando por posición, React ve que en el índice 0 el texto pasó de «Urbana Clásica» a «Eléctrica Pro», en el 1 de «Eléctrica Pro» a «Urbana Clásica», en el 2 de «Carga Max» a «Eléctrica Pro», y que hay un elemento nuevo en el 3. Conclusión: actualiza el contenido de las tres tarjetas y añade una cuarta. En realidad solo había que insertar una tarjeta al principio y no tocar las demás.
Además de ser ineficiente, es incorrecto: el estado interno de cada tarjeta (un desplegable abierto, una animación, un campo de horas rellenado) se queda pegado a la posición y acaba asociado a la bicicleta equivocada.
La solución es la prop key: una identidad estable que le dice a React «este elemento es este, independientemente de dónde esté ahora».
Con key={bicicleta.id}, React deja de comparar por posición y compara por identidad. Ve que bici-001, bici-002 y bici-003 ya existían y simplemente se han movido, y que bici-005 es nueva. Resultado: una sola inserción, y cada tarjeta conserva su propio estado, siga en la posición que siga.
Las reglas esenciales de key, en una frase cada una:
- Debe ser única entre hermanos (no en toda la aplicación).
- Debe ser estable: la misma clave para el mismo dato en todos los renders.
- El identificador del dato (
bicicleta.id) es casi siempre la mejor elección. - Nunca uses el índice del array si la lista puede reordenarse, filtrarse o crecer por el principio: el índice es exactamente la posición, así que no aporta identidad alguna y reproduce el problema que intentabas resolver.
- Y nunca
Math.random(): sería distinta en cada render, así que React destruiría y recrearía la lista entera cada vez.
Aquí solo necesitabas entender por qué existen las key, que es una consecuencia directa del algoritmo de reconciliación. La mecánica completa de pintar listas se estudia en Listas y Claves.
- Render, commit y repintado del navegador
Tres palabras que suenan parecidas y designan cosas distintas. Confundirlas hace incomprensibles la mitad de las conversaciones sobre rendimiento en React.
| Término | Quién lo hace | Qué es | ¿Es caro? |
|---|---|---|---|
| Render | React | Ejecutar tus funciones de componente y comparar árboles en memoria | Barato |
| Commit | React | Aplicar al DOM real las diferencias detectadas | Depende de cuántas haya |
| Repintado (paint) | El navegador | Recalcular geometría y dibujar píxeles en pantalla | Puede ser muy caro |
La secuencia completa, ordenada:
sequenceDiagram
participant U as Usuario
participant R as React
participant D as DOM
participant B as Navegador
U->>R: Interacción (cambio de estado)
R->>R: Render: ejecuta los componentes
R->>R: Reconciliación: compara árboles
alt Hay diferencias
R->>D: Commit: aplica los cambios
D->>B: Reflow y repintado
B-->>U: Pantalla actualizada
else No hay diferencias
R-->>R: Fin: el DOM no se toca
end
Fíjate en que el navegador repinta solo si hubo commit, y hubo commit solo si hubo diferencias. Cada eslabón puede cortar la cadena.
- Un render no siempre toca el DOM
De todo lo anterior se deriva la afirmación que más malentendidos deshace:
Que un componente se renderice no significa que el DOM cambie.
React puede ejecutar tu componente, obtener exactamente el mismo árbol de elementos que antes, no encontrar ninguna diferencia y terminar sin tocar un solo nodo. El coste de esa operación es solo el de ejecutar tus funciones y comparar objetos en memoria: normalmente, irrelevante.
Ejemplo concreto. Supón un contador de bicicletas que se recalcula en cada render:
function ResumenFlota() {
const disponibles = bicicletas.filter((b) => b.estado === 'disponible').length;
return <p>{disponibles} bicicletas disponibles</p>;
}Si el componente se renderiza de nuevo pero disponibles sigue valiendo 3, React genera <p>3 bicicletas disponibles</p>, lo compara con el anterior, ve que es idéntico y no toca el DOM. El usuario no percibe absolutamente nada, no hay reflow, no hay repintado.
Las implicaciones prácticas:
- Un render de más no es automáticamente un problema de rendimiento. Solo lo es cuando ocurre muy a menudo, sobre árboles muy grandes, o cuando dentro se hacen cálculos pesados.
- Optimizar antes de medir es un error clásico. Existen herramientas para evitar renders innecesarios (
React.memo,useMemo,useCallback) y son el contenido del Módulo 8, pero aplicarlas «por si acaso» añade complejidad y suele empeorar el resultado. Primero se mide, con el Profiler de React DevTools; después se optimiza lo que la medición señale. - Lo que sí debes evitar siempre es hacer trabajo pesado dentro de la función del componente: llamadas de red, bucles enormes, operaciones sobre miles de elementos. Eso se ejecuta en cada render, y ahí el coste es real.
Con esto tienes el modelo mental completo: tus componentes describen, React compara, y solo la diferencia llega al DOM.
Errores Comunes y Consejos
- Creer que el Virtual DOM es «más rápido» siempre. Es más rápido que repintar todo a mano y muchísimo más sostenible, pero no bate a un código imperativo mínimo y perfectamente optimizado. Su valor está en obtener un resultado casi óptimo por defecto.
- Pensar que renderizar es pintar. Renderizar es ejecutar tus funciones y comparar objetos. Pintar lo hace el navegador, y solo después de un commit con cambios reales.
- Cambiar el tipo del elemento contenedor según una condición. Provoca la destrucción del subárbol y la pérdida silenciosa del estado. Mantén el tipo y cambia las props.
- Usar el índice del array como
keyen listas que se reordenan, filtran o crecen por el principio. Es la causa número uno de estados que aparecen «pegados» a la fila equivocada. - Usar
Math.random()oDate.now()comokey. Destruye y recrea la lista completa en cada render: el peor rendimiento posible, y además pierde el foco y el scroll. - Escribir componentes impuros que modifican variables externas, escriben en
localStorageo hacen peticiones directamente en el cuerpo de la función. React puede ejecutarlos varias veces; los efectos secundarios tienen su sitio y se estudian en Hook useEffect. - Optimizar sin medir. Añadir memorización preventiva complica el código y a menudo lo ralentiza. Mide primero (lección 08-05).
- Consejo: cuando algo «se borre solo» en tu interfaz, pregúntate qué elemento cambió de tipo o de posición en el árbol. La respuesta casi siempre está ahí.
Ejercicios
Ejercicio 1
Para cada par de renders, indica qué hace React (reutiliza el nodo, o lo destruye y lo recrea) y si el estado interno de los componentes hijos sobrevive.
Caso A
// antes
<div className="tarjeta"><FormularioReserva /></div>
// después
<div className="tarjeta tarjeta--activa"><FormularioReserva /></div>Caso B
// antes
<div className="tarjeta"><FormularioReserva /></div>
// después
<section className="tarjeta"><FormularioReserva /></section>Caso C
Ejercicio 2
El catálogo de CicloUrbano muestra una lista de bicicletas y cada tarjeta tiene un campo donde el usuario escribe cuántas horas quiere reservar. El código usa el índice como clave:
{bicicletasVisibles.map((bicicleta, indice) => (
<TarjetaBicicleta key={indice} bicicleta={bicicleta} />
))}El usuario escribe «3» en la tarjeta de la «Carga Max», que está en tercera posición. Después activa el filtro «solo disponibles», que elimina la primera bicicleta de la lista porque está alquilada. Describe qué verá el usuario, explica por qué ocurre y corrige el código.
Ejercicio 3
Un compañero afirma: «He medido con el Profiler y este componente se renderiza 40 veces por segundo mientras el usuario arrastra el control de horas. Hay que envolverlo en React.memo ya mismo». El componente en cuestión es este:
function ResumenPrecio({ precioHora, horas }) {
return <p>Total: {(precioHora * horas).toFixed(2)} €</p>;
}¿Es correcto su razonamiento? Justifica la respuesta usando los conceptos de render, commit y repintado.
Soluciones
Solución 1.
Caso A — Reutiliza. El tipo es el mismo (div → div) y la posición también. React conserva el nodo del DOM y solo actualiza el atributo className. FormularioReserva se considera el mismo componente, se vuelve a ejecutar y conserva su estado: lo que el usuario hubiera escrito sigue ahí.
Caso B — Destruye y recrea. div y section son tipos distintos, así que React aplica la primera heurística: elimina el div con todo su subárbol y crea un section nuevo. FormularioReserva se desmonta y se vuelve a montar desde cero: el estado se pierde. Es el caso peligroso, porque el contenido interior parece idéntico.
Caso C — Destruye y recrea. El contenedor div sí se reutiliza, pero su hijo pasa de TarjetaBicicleta a FilaBicicleta: componentes distintos en la misma posición. React desmonta el primero y monta el segundo, y el estado se pierde. Que ambos muestren datos parecidos es irrelevante: para React son tipos diferentes.
Solución 2.
Qué ve el usuario: el «3» que había escrito para la «Carga Max» aparece ahora en la tarjeta de otra bicicleta, y la «Carga Max» muestra el campo vacío o el valor de otra. El dato «salta» de tarjeta.
Por qué ocurre: con key={indice}, la clave del tercer elemento es 2 antes y después del filtrado. Pero al eliminarse la primera bicicleta, en el índice 2 ya no está la «Carga Max», sino la que antes ocupaba el índice 3. React ve la misma clave 2 en la misma posición, concluye que es el mismo componente, conserva su estado y solo actualiza las props. Resultado: el estado del usuario se queda anclado a la posición, no a la bicicleta. El índice no es una identidad: es literalmente la posición, justo lo que key debía dejar de usar.
Corrección:
{bicicletasVisibles.map((bicicleta) => (
<TarjetaBicicleta key={bicicleta.id} bicicleta={bicicleta} />
))}Ahora la clave de la «Carga Max» es bici-003 esté donde esté. Al filtrar, React reconoce que ese componente sigue existiendo, lo mueve de posición y conserva su estado con la bicicleta correcta. Además, al detectar que solo desapareció un elemento, hace una única eliminación en el DOM en lugar de reescribir toda la lista.
Solución 3.
El razonamiento no es correcto, o al menos es prematuro. Confunde «render» con «coste».
- El render de
ResumenPrecioconsiste en una multiplicación, untoFixedy la creación de un objeto de elemento minúsculo. Cuarenta de esas operaciones por segundo son irrelevantes para cualquier dispositivo actual. - El commit solo ocurre si el resultado cambió. Y aquí sí cambia —el usuario está arrastrando el control de horas, luego el total varía—, pero se traduce en una sola actualización de texto: sin reflow de la página, sin inserciones ni eliminaciones de nodos.
- El repintado afecta a una línea de texto. Es de las operaciones más baratas que puede hacer un navegador.
Además, React.memo no ayudaría en absoluto en este caso: su función es evitar renders cuando las props no cambian, pero aquí horas cambia en cada movimiento del control. Añadirlo introduciría una comparación de props en cada render sin evitar ni uno solo: coste neto positivo, beneficio cero.
El enfoque correcto: un número alto de renders no es un diagnóstico, es un dato. Hay que medir con el Profiler cuánto tiempo consumen esos renders y si algún fotograma se pierde. Si el arrastre va fluido, no hay nada que arreglar. Y si hubiera un problema, casi seguro estaría en un componente hermano que hace trabajo pesado y se renderiza sin necesidad, no en este. Estas herramientas y su método de aplicación son el contenido del Módulo 8.
Conclusión
Ya conoces el motor que hay debajo de React. Tus componentes no generan HTML: producen objetos ligeros que forman un árbol en memoria, el llamado Virtual DOM. Cuando algo cambia, React recorre tres fases —disparo, render con reconciliación y commit— y aplica al DOM real únicamente las diferencias que ha encontrado, porque crear objetos es barato y tocar el DOM es caro. Su algoritmo se apoya en dos heurísticas que ahora sabes leer: mismo tipo en la misma posición se reutiliza y conserva el estado; distinto tipo se destruye y lo pierde, y en las listas hace falta una identidad estable (key) porque la posición no basta. Y tienes clara la distinción entre render, commit y repintado, que es lo que permite afirmar sin contradicción que un render no siempre toca el DOM.
Con esta lección cierras el Módulo 1. Has recorrido el camino completo desde el porqué hasta el cómo: sabes qué problema resuelve React y cuándo encaja, tienes el proyecto CicloUrbano montado con Vite y funcionando con recarga en caliente, has escrito tus primeros componentes propios, dominas la sintaxis JSX con sus reglas y su interpolación, y entiendes el mecanismo de renderizado que lo sostiene todo. Ya no estás copiando código: estás construyendo con criterio.
A partir de aquí toca profundizar en la pieza central de React. En el Módulo 2: Componentes de React aprenderás a diseñar componentes bien delimitados y reutilizables, a leer el código heredado escrito con clases, a pasarles datos desde fuera con props para que tus tarjetas dejen de ser fijas, a darles memoria propia con el estado —el otro disparador del render que acabas de estudiar— y a aplicarles estilos con estrategias que aguanten el crecimiento de la aplicación. CicloUrbano empieza de verdad en la próxima lección.
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
