Cómo React renderiza
"Render" es una de las palabras más usadas en React y una de las menos examinadas. Entender qué sucede realmente entre una actualización de estado y los píxeles cambiando en la pantalla aclara mucho: por qué los componentes se ejecutan cuándo lo hacen, por qué la mayoría de los re-renders cuesta prácticamente nada, y dónde debería enfocarse el trabajo real de optimización. Este capítulo construye ese modelo mental. Los dos capítulos siguientes, Memoización y Code splitting, lo ponen en práctica.
Un render es una llamada a función
Cuando React "renderiza" un componente, llama a tu función de componente:
function Counter() {
const [count, setCount] = useState(0)
console.log('Counter renderizado') // se ejecuta cada vez que React llama esta función
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}Ese es el truco completo. La función se ejecuta de principio a fin, cualquier cálculo dentro de ella se ejecuta nuevamente, y devuelve JSX describiendo cómo debería verse la UI ahora. Nada de eso involucra el DOM del navegador. Un render produce una descripción; no toca la página.
Esa distinción importa porque estas dos cosas tienen costos totalmente diferentes. Llamar una función JavaScript y construir una descripción es rápido. Cambiar el DOM real, lo que dispara el trabajo de layout y paint en el navegador, es la parte costosa. Todo el diseño de React se inclina hacia hacer la cosa barata libremente y la cosa costosa lo menos posible.
Los tres pasos
Un único "re-render" atraviesa tres pasos. El disparador es generalmente una actualización de estado, aunque el mount inicial, un componente padre renderizando arriba del componente, y un nuevo valor de context ejecutan la misma maquinaria.
- Render. React llama la función del componente cuyo estado cambió, y luego, recursivamente, cada componente que devuelve. El resultado es un DOM virtual fresco: una descripción ligera en memoria de esa parte de la UI.
- Reconciliación. React ejecuta un algoritmo de diffing comparando el nuevo DOM virtual contra el anterior, averiguando exactamente qué cambió entre ellos.
- Commit. Las diferencias, y solo las diferencias, se aplican al DOM real. Esta es la parte que el usuario realmente puede ver.
El curso ofrece una analogía que vale la pena mantener en mente. Un arquitecto actualizando un edificio primero redibuja el plano (render), luego lista qué cambios el nuevo plano realmente requiere (reconciliación), y solo entonces la cuadrilla de construcción toca el edificio (commit). Redibujar un plano es rápido. La construcción es donde van el tiempo y el dinero, así que la cuadrilla hace el menor trabajo que la lista permite.
El renderizado y la reconciliación se mantienen rápidos, y el commit se limita a lo que el diff encontró, por eso React se siente rápido por defecto. Cuando algo sí se vuelve lento, el Profiler te dice cuál paso culpar en lugar de dejarte adivinando.
Cada clic en el botón Counter ejecuta los tres: el log se dispara, React difea el resultado, y el commit actualiza el nodo de texto del botón y nada más a su alrededor.
El renderizado es recursivo, y eso generalmente está bien
Cuando un componente renderiza, React renderiza todo lo que devuelve, luego todo lo que esos componentes devuelven, hasta el fondo de cada rama antes de pasar a la siguiente. Un cambio de estado en un componente padre por lo tanto re-renderiza todos sus descendientes por defecto, sin importar si reciben el estado cambiado como props.
Eso suena derrochador hasta que separas los pasos nuevamente. Esos renders hijo son llamadas a función produciendo descripciones. Durante la reconciliación, React no encuentra atributos cambiados en ninguno de ellos, así que el commit no tiene trabajo de DOM que hacer para ese subárbol. El trabajo de DOM visible al usuario se mantiene limitado a lo que realmente cambió. Re-renderizar un subárbol que no hace commit es el caso normal y saludable, y para la inmensa mayoría de los componentes es demasiado barato para medir.
Deja de estar bien en dos situaciones: cuando un componente hace trabajo costoso durante su render, o cuando un subárbol es tan grande que incluso los renders baratos se suman. Esos son exactamente los casos que Memoización aborda. Resiste la tentación de alcanzarla antes de tener evidencia, lo que nos lleva a medir.
Mide antes de optimizar
React ya es rápido, y la reconciliación ya mantiene las actualizaciones del DOM mínimas. El consejo del curso es directo: sé capaz de medir un problema de rendimiento antes de aplicar una técnica para arreglarlo, y pesa cada optimización contra la legibilidad del código que complica. La astucia que nadie puede mantener también es un costo.
Dos herramientas cubren la mayoría de necesidades de medición:
- La pestaña Performance del navegador. Graba una sesión, realiza la interacción lenta, detente, e inspecciona qué se ejecutó y cuánto tiempo tomó. Su throttling de CPU (prueba un desaceleramiento de 4x o 6x) y throttling de red te permiten que tu máquina de desarrollo rápida simule los dispositivos más lentos y conexiones que tus usuarios realmente tienen. Los problemas invisibles en tu laptop aparecen inmediatamente.
- El Profiler de React DevTools. Una extensión de navegador del equipo de React, viviendo en su propia pestaña Profiler. El mismo flujo de graba-actúa-detente, pero la salida es de forma React: qué componentes renderizaron, por qué renderizaron, cuánto tiempo tomó cada uno, y cuánto tiempo tomó el commit. Para diagnosticar apps de React específicamente, generalmente es la herramienta más directa.
StrictMode: un pasamanos para desarrollo
StrictMode es un componente que envuelves alrededor de tu app (o cualquier subárbol) para activar chequeos solo en desarrollo. Es el wrapper que Setup pone alrededor de <App /> en main.jsx.
En desarrollo, StrictMode deliberadamente invoca dos veces tus funciones de componente, junto con las otras funciones que React espera que sean puras: inicializadores de useState y useReducer, los updaters que pasas a un setter, reducers, y cálculos de useMemo. Ejecuta cada efecto una vez extra, configurándolo, limpiándolo, y configurándolo de nuevo, y reinyecta callbacks de ref. También advierte sobre APIs deprecadas. En una build de producción no hace nada, así que nunca ralentiza o re-renderiza dos veces la app que tus usuarios ven.
Ejecutar dos veces suena como sabotaje hasta que ves qué atrapa. Una función de componente se supone que es pura: mismos inputs, mismo output, sin efectos secundarios durante el render. Si renderizar dos veces produce un resultado diferente que renderizar una vez, el componente estaba escondiendo un bug.
El curso demuestra esto con un componente que llama push en un array definido fuera de sí mismo durante el render; la página se ve bien hasta que cualquier cambio de estado re-ejecuta la función y hace push de un duplicado. Bajo StrictMode el duplicado aparece en el primer load, y la solución (copiar el array antes de modificarlo, o mover el trabajo fuera del render) se sigue de ello.
La pureza cubre tus updaters
El mismo requisito de pureza cubre el updater en setCount(c => c + 1), ya que esa función también se ejecuta dos veces.
Las pruebas de re-ejecutar efecto prueban el mismo contrato desde el otro lado. Effects dueño de la regla de cleanup y muestra cómo se ve una faltante bajo StrictMode, cuando un setInterval sin limpiar te deja contando de dos en dos y filtrando un timer por mount.
Ver más bugs en desarrollo se siente al revés al principio, pero ese es el punto entero. Cada bug que StrictMode expone ya existía y de otro modo habría esperado a producción para presentarse.
Nota de versión
El comportamiento de efecto llegó en React 18: al mount, StrictMode ejecuta la setup de cada efecto, luego su cleanup, luego setup de nuevo. Artículos más viejos describen StrictMode como solo re-renderizando componentes. El curso escribe el wrapper como React.StrictMode; con named imports es <StrictMode>.
Envuelve tu app en StrictMode mientras construyes: ejecuta cosas dos veces a propósito en desarrollo para ayudarte a detectar bugs temprano, y se apaga a sí mismo en la app terminada.
Siguiente: Memoización, donde la igualdad referencial decide qué puede saltarse React.

