Inicio / Artículos

Explicación de la renderización en React: Actualizaciones de estado a píxeles de pantalla

Cómo las fases de renderizado, reconciliación y confirmación de React se conectan con el renderizado del navegador: layout, pintado y composición, desde una actualización de estado hasta los píxeles reales de la pantalla.

Editor: REACTAPP.TOP17 min de lectura4015 palabras

Fuentes: Rendering Lifecycle in React: From State Update to Pixels on the Screen

Al trabajar con React, es común escuchar la frase “el componente se vuelve a renderizar”. Pero, ¿qué significa realmente el proceso de renderizado en su interior?

Aquí surgen algunas preguntas lógicas. ¿React envía actualizaciones al DOM en el momento en que cambia el estado? ¿Un cambio de estado obliga a que cada componente se vuelva a renderizar? Y cuando React vuelve a renderizar algo, ¿significa eso que el navegador dibuja inmediatamente toda la página? Resulta que ninguna de estas afirmaciones es cierta.

Para comprender realmente el ciclo de vida del renderizado, es necesario entender dos sistemas separados que trabajan juntos:

El propio ciclo de vida de renderizado de React y la tubería de renderizado del navegador.

Una vez que veas cómo se conectan estos dos sistemas, conceptos como la reconciliación, la fase de confirmación, useEffect, useLayoutEffect, el volver a renderizar y la memorización dejan de parecer magia y comienzan a tener sentido.

1. La visión general

A un nivel alto, el flujo es el siguiente:

User Interaction
      │
      ▼
State / Props Change
      │
      ▼
┌──────────────────────┐
│     React Render     │
│                      │
│  Component executes  │
│  New UI is returned  │
└──────────┬───────────┘
           │
           ▼
     Reconciliation
           │
           ▼
┌──────────────────────┐
│     Commit Phase     │
│                      │
│  Update real DOM     │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────────┐
│    Browser Rendering     │
│                          │
│ Style → Layout → Paint   │
│           → Composite    │
└────────────┬─────────────┘
             │
             ▼
           Screen

La idea clave es esta:

React determina cómo debe verse la interfaz de usuario y qué cambios en el DOM son necesarios. Luego, el navegador toma esos cambios del DOM y los convierte en píxeles reales en la pantalla.

2. ¿Qué significa “renderizado”?

El término renderizado se utiliza en más de un sentido.

En el contexto de React, renderizado generalmente significa lo siguiente:

React llama a la función de tu componente y determina cuál debe ser la interfaz de usuario resultante.

Considera este componente:

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button>
      Count: {count}
    </button>
  );
}

Cuando React lo renderiza, se ejecuta el cuerpo de la función:

Counter()
   ↓
returns React element
   ↓
<button>Count: 0</button>

Esto no significa que el navegador ya haya dibujado el botón en la pantalla.

Antes de que ocurra algo visual, React aún debe decidir si el DOM real necesita cambiar.

En resumen:

React Render
     ≠
DOM Update
     ≠
Browser Paint

El renderizado y la actualización del DOM son dos operaciones distintas.

3. Ciclo de vida del renderizado en el navegador

Antes de adentrarnos en los detalles internos de React, es útil comprender qué hace el propio navegador.

Imagínese que tiene este marcado:

<h1 class="title">
  Hello World
</h1>

Junto con esta hoja de estilo:

.title {
  color: red;
  font-size: 30px;
}

Antes de que este contenido aparezca visualmente, el navegador sigue una serie de pasos internos.

Una versión simplificada de ese proceso es la siguiente:

HTML
 ↓
DOM
 ↓
CSS
 ↓
CSSOM
 ↓
Render Tree
 ↓
Layout
 ↓
Paint
 ↓
Composite
 ↓
Screen

Veamos cada etapa en detalle.

4. HTML → DOM

El navegador lee el HTML y construye el DOM, abreviatura de Document Object Model.

Dado este marcado:

<body>
  <h1>Hello World</h1>
  <p>Welcome</p>
</body>

El navegador crea una estructura en forma de árbol más o menos así:

Document
   │
   └── body
       ├── h1
       │   └── "Hello World"
       │
       └── p
           └── "Welcome"

Luego, JavaScript puede consultar y manipular directamente esta estructura:

document.querySelector("h1");

En esencia, el DOM responde a una pregunta:

¿Qué elementos existen en la página?

5. CSS → CSSOM

Junto con el DOM, el navegador también analiza tu CSS y construye el CSSOM, o CSS Object Model.

Por ejemplo:

h1 {
  color: red;
  font-size: 30px;
}

A partir de esto, el navegador determina qué estilos se aplican a cada elemento.

Conceptualmente, se ve así:

h1
 ├── color: red
 └── font-size: 30px

El CSSOM responde a otra pregunta:

¿Cómo debe estilizarse visualmente cada elemento?

6. DOM + CSSOM → Árbol de renderizado

A continuación, el navegador combina el DOM y el CSSOM para generar un Árbol de Renderizado.

Hay una sutileza que merece ser mencionada:

No todos los nodos del DOM terminan representados en el Árbol de Renderizado.

Por ejemplo, tome este marcado:

<div class="hidden">
  Hello
</div>

Combinado con esta regla:

.hidden {
  display: none;
}

El elemento div está presente en el DOM:

DOM
 └── div

Pero como lleva consigo:

display: none;

es excluido por completo del árbol de renderizado visual.

7. Layout

Una vez que el navegador sabe exactamente qué elementos deben mostrarse, calcula su geometría.

Esto implica calcular cosas como:

  • Ancho
  • Altura
  • Posición
  • Márgenes
  • Relleno
  • Coordenadas
  • Cómo los elementos se relacionan espacialmente entre sí

Tome esta regla como ejemplo:

.box {
  width: 200px;
  height: 100px;
  margin-left: 50px;
}

El navegador debe generar valores concretos de esta manera:

x      = 50px
y      = ...
width  = 200px
height = 100px

Este paso de cálculo se conoce como Layout y también se le denomina frecuentemente Reflow.

8. Paint

Una vez finalizado el layout, el navegador dispone de coordenadas para cada elemento visible.

El siguiente paso consiste en dibujar cómo se ven realmente esos elementos.

Considere este estilo:

.box {
  background: blue;
  color: white;
  border: 2px solid black;
}

El proceso de Paint abarca elementos como:

  • Fondo
  • Texto
  • Bordes
  • Sombras
  • Imágenes
  • Otros elementos visuales

En secuencia:

Layout
  ↓
Paint
  ↓
Pixels

9. Composite

Los navegadores actuales pueden dividir una página en varias capas distintas.

Por ejemplo:

Layer 1 → Page background
Layer 2 → Header
Layer 3 → Content
Layer 4 → Modal

Luego, el compositor del navegador combina todas estas capas en la única imagen que finalmente aparece en la pantalla.

Ciertas propiedades CSS, como:

transform
opacity

Por lo general, se puede animar únicamente mediante composición, evitando así el trabajo adicional de diseño que requieren las propiedades que afectan la geometría.

Esa es una de las razones por las cuales animar transform suele ser el enfoque preferido.

10. Ciclo de vida de renderizado en React

Ya que hemos abordado el lado del navegador, veamos cómo maneja React el renderizado.

Un modelo mental útil lo divide en cuatro etapas:

1. Trigger
2. Render
3. Reconciliation
4. Commit
5. Browser Rendering

Analicemos cada una de ellas.

11. Fase 1: Desencadenante

Antes de que ocurra cualquier otra cosa, React necesita una señal que indique:

"Es posible que sea necesario actualizar la interfaz de usuario."

Esta señal se conoce como desencadenante de renderizado.

Los desencadenantes típicos incluyen:

1. Actualización de estado: setCount(10);

2. Cambio de props: <Child count={count} />

Cuando un componente padre se vuelve a renderizar con un nuevo valor para count, sus hijos pueden recibir nuevos props como resultado.

3. Actualización de contexto: useContext(MyContext);

Cada vez que cambia el valor leído del contexto, los componentes que lo consumen pueden necesitar actualizarse.

4. Actualización del almacén externo: Las bibliotecas y APIs también pueden provocar actualizaciones en React.

Algunos ejemplos son:

Redux
Zustand
useSyncExternalStore

Montar una aplicación por primera vez también cuenta como un desencadenante.

12. Fase 2 — Renderizado

Una vez que React detecta una actualización, pasa a la fase de renderizado, donde ejecuta los componentes para determinar la nueva interfaz de usuario.

Tomemos este ejemplo:

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count}
    </button>
  );
}

Al principio, count es 0. React llama a Counter() y genera:

<button>
  Count: 0
</button>

Cuando se hace clic en el botón y esto se ejecuta:

setCount(c => c + 1);

count pasa a ser 1, y React vuelve a ejecutar el componente, lo que da como resultado:

<button>
  Count: 1
</button>

13. Importante: Renderizar NO significa actualizar el DOM

Esta es una distinción crucial en el modelo de React.

Cuando React ejecuta esta función:

function Counter() {
  console.log("Counter rendered");

  return <button>Count: 1</button>;
}

simplemente está calculando cómo debería verse la interfaz de usuario. Esto no implica automáticamente que el DOM haya cambiado o que el navegador haya vuelto a dibujar algo.

La secuencia real es la siguiente:

Component executes
       ↓
React creates new element representation
       ↓
Reconciliation
       ↓
Determine required DOM changes
       ↓
Commit changes

Lo cual conduce a una regla fundamental:

Renderizar un componente no se traduce automáticamente en una actualización del DOM.

14. Fase 3: Reconciliación

En esta etapa, React compara la interfaz de usuario antigua y nueva para determinar exactamente qué es diferente.

Supongamos que el árbol anterior se veía así:

button
 └── "Count: 0"

Y el árbol nuevo se ve así:

button
 └── "Count: 1"

React puede determinar:

button → same
text   → changed

Por lo tanto, solo necesita modificar la parte del DOM que realmente ha cambiado:

button.textContent = "Count: 1";

El objetivo principal es evitar desmontar y reconstruir todo el árbol DOM cuando solo ha cambiado una pequeña parte.

15. Claves y reconciliación

Las claves son cruciales cuando React trabaja con listas.

Por ejemplo:

items.map(item => (
  <li key={item.id}>
    {item.name}
  </li>
))

React depende de las claves para rastrear qué elemento es cuál entre diferentes renders. Supongamos que comenzamos con:

Before:

A
B
C

y terminamos con:

After:

A
C

Con claves estables, React puede deducir correctamente:

A → same
B → removed
C → same

Esto proporciona a React información mucho más fiable con la que trabajar durante la reconciliación.

Evite depender de los índices del array como claves cuando los elementos de la lista puedan reordenarse, añadirse o eliminarse.

16. Fase 4 — Confirmar

Una vez que React determina qué cambios son necesarios, pasa a la fase de confirmación, donde aplica realmente esos cambios al DOM real.

Imagínese un elemento de botón cuya etiqueta pasa de mostrar un conteo de cero a uno una vez completada esta fase.

En este punto, el árbol interno de React y el DOM en tiempo real finalmente coinciden.

La fase de confirmación es un paso separado de la fase de renderizado:

Render Phase
    ↓
Calculate what should change

Commit Phase
    ↓
Actually apply DOM changes

17. Fase de Renderizado vs Fase de Confirmación

Comprender esta división es una de las cosas más comunes que investigan los entrevistadores.

Fase de Renderizado

Durante esta fase, React:

  • Ejecuta las funciones de los componentes
  • Determina la próxima versión de la interfaz de usuario
  • Efectúa la reconciliación
  • Identifica qué cambios son necesarios
Component
   ↓
React elements
   ↓
Reconciliation

Fase de Confirmación

Durante esta fase, React:

  • Aplica las mutaciones reales del DOM
  • Actualiza todas las referencias
  • Ejecuta los efectos de layout relacionados con esta actualización
React result
    ↓
Real DOM

Aquí hay una representación simplificada del flujo:

             React
               │
               ▼
        ┌──────────────┐
        │ Render Phase │
        └──────┬───────┘
               │
               ▼
        ┌───────────────┐
        │ Commit Phase  │
        └──────┬────────┘
               │
               ▼
            Real DOM

18. ¿Qué sucede después del commit?

Una vez finalizada la fase de commit, el navegador toma el control y se da cuenta de que el DOM ha cambiado.

Dependiendo de qué haya cambiado, el navegador podría necesitar pasar por varias etapas:

DOM Changes
    ↓
Style Calculation
    ↓
Layout
    ↓
Paint
    ↓
Composite

No todos los cambios requieren todas estas etapas para que haya un efecto real; por ejemplo, un cambio podría necesitar solo una actualización visual sin requerir un recálculo completo del layout.

Este es exactamente el punto en el que el propio ciclo de vida de React pasa el control al pipeline de renderizado del navegador descrito anteriormente.

19. useLayoutEffect

useLayoutEffect se ejecuta después de que React haya aplicado las actualizaciones en el DOM, pero antes de que el navegador tenga la oportunidad de dibujar las nuevas imágenes.

La secuencia es la siguiente:

React Render
     ↓
Commit
     ↓
DOM updated
     ↓
useLayoutEffect
     ↓
Browser Paint
function Tooltip() {
  const ref = useRef(null);

  useLayoutEffect(() => {
    const rect = ref.current.getBoundingClientRect();

    console.log(rect.width);
  }, []);

  return (
    <div ref={ref}>
      Tooltip
    </div>
  );
}

Este hook es la herramienta adecuada cuando necesitas:

  • Medir elementos en el DOM
  • Leer los valores de layout actuales
  • Aplicar ajustes visuales de forma síncrona, antes de que el usuario vea algo

Una precaución: si el trabajo dentro de useLayoutEffect es intensivo, puede retrasar el dibujo y hacer que la interfaz parezca lenta.

20. useEffect

useEffect, en contraste, está diseñado para efectos que no necesitan bloquear el proceso de dibujo del navegador.

useEffect(() => {
  fetch("/api/products");
}, []);
Render
   ↓
Commit
   ↓
Browser Paint
   ↓
useEffect

Los detalles reales de programación son un poco más sutiles que esto, pero la regla práctica clave es:

Solo utilice useLayoutEffect cuando algo debe ocurrir antes de que el navegador dibuje; use useEffect para cualquier tarea que pueda ejecutarse después de que la interfaz ya esté visible.

21. Ejemplo completo

import { useEffect, useLayoutEffect, useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  console.log("Render");

  useLayoutEffect(() => {
    console.log("Layout Effect");
  });

  useEffect(() => {
    console.log("Effect");
  });

  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count}
    </button>
  );
}

Conceptualmente, la secuencia de eventos se ve así:

User clicks button
        ↓
setCount()
        ↓
State update scheduled
        ↓
Counter() executes
        ↓
"Render"
        ↓
React reconciles
        ↓
React commits DOM update
        ↓
"Layout Effect"
        ↓
Browser paints updated UI
        ↓
"Effect"

22. ¿El volver a renderizar un padre hace que se renderice el hijo?

Tome este ejemplo:

function Parent() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount(c => c + 1)}>
        {count}
      </button>

      <Child />
    </>
  );
}

Cuando se actualiza count:

Parent renders
       ↓
Child is encountered
       ↓
Child may render as part of reconciliation

So,

Parent state update
      ↓
Parent render
      ↓
Child can render

Este comportamiento es una de las razones por las que existe React.memo como herramienta de optimización.

23. React.memo

Supongamos que tiene:

const Child = React.memo(function Child() {
  console.log("Child rendered");

  return <p>Hello</p>;
});

Si el padre vuelve a renderizarse pero los props pasados al hijo permanecen idénticos en términos de referencia, React puede omitir por completo el volver a renderizar ese hijo memorizado.

Aquí está la idea de forma visual:

Parent update
     ↓
Parent renders
     ↓
React.memo checks Child props
     ↓
Props unchanged
     ↓
Skip Child render

No obstante, tenga en cuenta lo siguiente:

React.memo le ofrece una forma rápida de mejorar el rendimiento, pero no garantiza que un componente nunca se vuelva a renderizar.

Los cambios en el contexto, el estado interno y otros factores pueden obligar a que se actualice, independientemente de la memorización.

24. useMemo y useCallback

Estos dos hooks suelen malinterpretarse.

useMemo: Memoriza un valor calculado.

const result = useMemo(() => expensiveCalculation(data), [data]);

useCallback: Memoriza una referencia a función.

const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

Ambos son realmente útiles en situaciones donde la igualdad referencial es importante para evitar tareas repetidas, especialmente al pasar propiedades a componentes hijos memorizados.

No obstante, usarlos en todas partes por defecto tiende a añadir complejidad al código sin obtener ningún beneficio real en términos de rendimiento.

25. Un renderizado de React no es lo mismo que un dibujo en el navegador

Vale la pena mencionar este punto explícitamente.

Imagínese el siguiente componente:

function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>
        {count}
      </button>

      <p>Hello</p>
    </div>
  );
}

Cuando count cambia:

App renders
     ↓
New React tree created
     ↓
Reconciliation
     ↓
Only count text differs
     ↓
Commit small DOM update
     ↓
Browser rendering

React no necesariamente reconstruirá este marcado desde cero:

<div>
  <button>...</button>
  <p>Hello</p>
</div>

26. DOM virtual: entender correctamente el modelo mental

Una afirmación común que se escucha es que React depende de un DOM virtual para acelerar el navegador. Eso es una simplificación excesiva.

Lo que realmente hace React es mantener una descripción interna de la interfaz de usuario en memoria y utilizar el proceso de reconciliación para determinar qué ha cambiado.

El propio navegador no tiene concepto de DOM virtual. Solo trabaja con elementos como HTML, el DOM, CSS y, en última instancia, píxeles.

Conceptualmente, el flujo es el siguiente:

React Component
      ↓
React Element Tree
      ↓
Reconciliation
      ↓
DOM Mutations
      ↓
Browser
      ↓
Pixels

El DOM virtual nunca es algo que el navegador renderice realmente.

27. Volver a renderizar vs Volver a pintar

Estos son dos conceptos distintos que no deben confundirse.

Volver a renderizar en React

Esto ocurre cuando la función de un componente se ejecuta nuevamente; esencialmente, Component() se ejecuta.

Volver a pintar en el navegador

Esto ocurre cuando el navegador vuelve a dibujar los píxeles en la pantalla debido a que alguna propiedad visual ha cambiado; es el paso de Pintar.

Así que tenga en cuenta: un volver a renderizar en React no es equivalente a un volver a pintar en el navegador.

Es completamente posible que un componente se vuelva a renderizar pero genere una estructura DOM idéntica. Por el contrario, el navegador puede volver a pintar por razones que no tienen nada que ver con la renderización de ningún componente React.

28. Reorganizar el flujo vs Volver a pintar

Tomemos este ejemplo: element.style.width = "500px";

Cambiar el ancho de un elemento suele obligar a un nuevo cálculo del diseño:

Style
 ↓
Layout
 ↓
Paint
 ↓
Composite

Ahora compárelo con: element.style.backgroundColor = "red";

Aquí, el navegador generalmente no necesita volver a realizar los cálculos geométricos:

Style
 ↓
Paint
 ↓
Composite

Y para ciertos cambios en transformaciones u opacidad, el navegador puede solo necesitar:

Composite

Comprender esta diferencia es muy importante cuando se optimizan animaciones o interfaces con altas demandas de renderizado.

29. Aplicando esto a un escenario real de React

Imaginemos una página típica de producto de comercio electrónico estructurada así:

Product Page
 ├── Navbar
 ├── Product Gallery
 ├── Product Information
 ├── Add To Cart
 ├── Reviews
 └── Recommendations

Supongamos que un usuario hace clic en el botón Añadir al carrito, lo que actualiza la cantidad en el carrito.

Conceptualmente, la secuencia de eventos podría verse así:

User clicks "Add to Cart"
           ↓
Cart state updates
           ↓
React schedules update
           ↓
Relevant components render
           ↓
React reconciles new tree
           ↓
Only required DOM changes are committed
           ↓
Browser performs necessary rendering work
           ↓
Updated cart count appears

En una aplicación bien estructurada, esta actualización del conteo del carrito no debería forzar la reconstrucción innecesaria de toda la interfaz de usuario. Por eso es tan importante tomar decisiones acertadas respecto a los límites de los componentes, dónde se almacena el estado, la memorización y la arquitectura general de renderizado.

30. Cuando el renderizado costoso se convierte en un problema de rendimiento

function ProductList({ products }) {
  return products.map(product => (
    <ExpensiveProductCard
      key={product.id}
      product={product}
    />
  ));
}

Supongamos que esta lista muestra 10,000 productos, y algún cambio en un estado no relacionado provoca trabajo innecesario en una gran cantidad de componentes; el rendimiento puede deteriorarse notablemente.

Las técnicas comunes de mitigación incluyen:

React.memo
      +
Stable props
      +
useMemo/useCallback where justified
      +
Virtualization
      +
Pagination
      +
Code splitting

En listas especialmente grandes, la virtualización suele ser particularmente efectiva:

10000 items
     ↓
Only visible ~20-50 items rendered

31. Cómo interactúa el renderizado con React concurrente

Las versiones más recientes de React incluyen capacidades de programación más avanzadas. React puede asignar prioridad a diferentes actualizaciones y, cuando sea apropiado, pausar o posponer el trabajo de renderizado.

El modelo mental clave a mantener es:

Render work
    ↓
Can be scheduled
    ↓
Can be interrupted in modern React
    ↓
Eventually committed

Este es exactamente el motivo por el cual los efectos secundarios no deberían encontrarse dentro de la lógica de renderizado de un componente:

function Component() {
  fetch("/api/data"); // ❌ Side effect during render

  return <div>Hello</div>;
}

En su lugar, utilice un gancho effect o un patrón adecuado para obtener datos. Lo ideal es que la fase de renderizado permanezca pura.

32. El caso a favor del renderizado puro

Conceptualmente, un componente de React debería comportarse como una función pura:

UI = f(props, state)

Con las mismas props y estado, siempre debería describir la misma interfaz de usuario. Por ejemplo:

function Greeting({ name }) {
  return <h1>Hello {name}</h1>;
}

Este comportamiento es predecible y seguro.

En contraste, hacer algo así dentro del renderizado es problemático:

function Component() {
  localStorage.setItem("x", "1"); // ❌
  fetch("/api");                  // ❌

  return <div>Hello</div>;
}

Esto introduce efectos secundarios en una fase que React podría ejecutar más de una vez o programar de maneras inesperadas.

Los efectos secundarios pertenecen a otro lugar: dentro de los efectos, los manejadores de eventos o los mecanismos de obtención de datos que ofrece tu framework.

33. Ciclo de vida de renderizado — Modelo mental completo

                    USER ACTION
                         │
                         ▼
               State / Props Update
                         │
                         ▼
                React Schedules Work
                         │
                         ▼
                 ┌──────────────┐
                 │    RENDER    │
                 │              │
                 │ Components   │
                 │ execute      │
                 └──────┬───────┘
                        │
                        ▼
                 Reconciliation
                        │
                        ▼
                 ┌──────────────┐
                 │    COMMIT    │
                 │              │
                 │ DOM mutation │
                 └──────┬───────┘
                        │
                        ▼
                 useLayoutEffect
                        │
                        ▼
              Browser Rendering
                        │
                        ▼
                 Style Calculation
                        │
                        ▼
                     Layout
                        │
                        ▼
                      Paint
                        │
                        ▼
                   Composite
                        │
                        ▼
                      SCREEN
                        │
                        ▼
                   useEffect

Preguntas comunes en entrevistas

P1. ¿Una actualización de estado actualiza inmediatamente el DOM?

No. Una actualización de estado simplemente programa el trabajo que React debe realizar. React renderiza el componente, compara el resultado con lo anterior y solo entonces aplica los cambios en el DOM que realmente son necesarios.

setState
  ↓
Render
  ↓
Reconciliation
  ↓
Commit
  ↓
DOM

P2. ¿Cada renderizado conlleva una actualización del DOM?

No. React puede renderizar un componente y concluir que la descripción de la interfaz resultante es idéntica a lo que ya está en pantalla; en ese caso, omite modificar el DOM.

Render
  ↓
Compare
  ↓
No meaningful DOM difference
  ↓
No DOM mutation

Q3. ¿El volver a renderizar en React fuerza al navegador a volver a pintar?

No. El renderizado en React y la pintura en el navegador son dos procesos independientes.

React Render ≠ Browser Paint

Q4. ¿Qué significa la reconciliación?

La reconciliación es el proceso mediante el cual React compara el árbol de UI recién calculado con el anterior para determinar exactamente qué necesita cambiar.

Q5. ¿Qué sucede durante la fase de commit?

Durante el commit, React aplica los cambios necesarios en el entorno anfitrión; por ejemplo, actualizando los nodos DOM reales en un navegador.

Q6. ¿En qué se diferencian useEffect y useLayoutEffect?

Una forma sencilla de recordarlo:

useLayoutEffect
→ after DOM commit, before paint

useEffect
→ after commit and generally after paint

Utiliza useLayoutEffect cuando necesites medir o ajustar el layout de forma síncrona antes de que el usuario vea el nuevo frame. Usa useEffect para la mayoría de los efectos secundarios que no requieren bloquear el proceso de dibujo.

P7. ¿Qué hace que un componente se renderice?

Los desencadenantes típicos son: un montaje inicial, una actualización de estado, un nuevo renderizado del padre, un cambio en las props, una actualización del contexto o una actualización desde un almacén externo.

P8. ¿Cómo se puede optimizar el rendering? [IMP]

En lugar de usar useMemo por defecto en todas partes, primero identifica dónde se encuentra el cuello de botella real. Luego considera estos enfoques:

1. Mantén el estado cerca de donde se utiliza

Evita una estructura en la que el estado esté en la parte superior y todos los descendientes dependan de él:

App
 ↓
Everything depends on state

prefer:

Feature
 ↓
Local state

Es preferible optar por una ubicación más restringida cuando en realidad no se necesita el estado global.

2. Memorizar selectivamente los componentes costosos

const ProductCard = React.memo(ProductCardComponent);

3. Tener cuidado con la creación de objetos que interrumpen la memorización

En lugar de crear repetidamente un objeto nuevo directamente en el código así:

<Child config={{ theme: "dark" }} />

Puede ser necesario contar con una referencia estable si Child está envuelto en React.memo y la identidad es importante; pero no solucione esto hasta que realmente sea un problema.

4. Virtualizar listas largas

En lugar de renderizar los 10,000 nodos DOM al mismo tiempo, renderice solo aquellos que estén actualmente visibles.

5. Posponer la carga de funciones costosas

const AdminDashboard = lazy(() => import("./AdminDashboard"));

Esto reduce la cantidad de JavaScript que debe descargarse y ejecutarse de antemano.

6. Preferir técnicas de renderizado compatibles con el navegador

Anime con propiedades económicas como transform y opacidad siempre que sea posible, y evite forzar recálculos costosos de layout en cada frame.

Lecturas relacionadas