Renderizado, Confirmación y Montaje
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Este documento hace referencia a la Nueva Arquitectura, que se está implementando activamente.
El renderizador de React Native realiza una secuencia de trabajo para renderizar la lógica de React en una plataforma anfitriona. Esta secuencia de trabajo se llama tubería de renderizado y ocurre tanto para renderizados iniciales como para actualizaciones del estado de la UI. Este documento explica la tubería de renderizado y cómo difiere en esos escenarios.
La tubería de renderizado puede dividirse en tres fases generales:
-
Renderizado: React ejecuta la lógica de la aplicación que crea un Árbol de Elementos de React en JavaScript. A partir de este árbol, el renderizador crea un Árbol de Sombras de React en C++.
-
Confirmación: Tras crear completamente un Árbol de Sombras de React, el renderizador dispara una confirmación. Esto promueve tanto al Árbol de Elementos de React como al nuevo Árbol de Sombras de React como el "próximo árbol" a montar. También programa el cálculo de su información de diseño.
-
Montaje: El Árbol de Sombras de React, ahora con los resultados del cálculo de diseño, se transforma en un Árbol de Vistas del Anfitrión.
Las fases de la tubería de renderizado pueden ocurrir en diferentes hilos. Consulta el documento Modelo de Subprocesos para más detalles.

Renderizado Inicial
Imagina que quieres renderizar lo siguiente:
function MyComponent() {
return (
<View>
<Text>Hello, World</Text>
</View>
);
}
// <MyComponent />
En el ejemplo anterior, <MyComponent /> es un Elemento de React. React reduce recursivamente este Elemento de React a un Componente de Anfitrión de React terminal invocándolo (o su método render si está implementado con una clase de JavaScript) hasta que cada Elemento de React no se pueda reducir más. Ahora tienes un Árbol de Elementos de React compuesto por Componentes de Anfitrión de React.
Fase 1. Render

Durante este proceso de reducción de elementos, a medida que se invoca cada Elemento de React, el renderizador también crea de manera síncrona un Nodo de Sombra de React. Esto ocurre solo para Componentes de Anfitrión de React, no para Componentes Compuestos de React. En el ejemplo anterior, el <View> conduce a la creación de un objeto ViewShadowNode, y el <Text> conduce a la creación de un objeto TextShadowNode. Cabe destacar que nunca existe un Nodo de Sombra de React que represente directamente a <MyComponent>.
Cada vez que React crea una relación padre-hijo entre dos Nodos de Elemento de React, el renderizador crea la misma relación entre los correspondientes Nodos de Sombra de React. Así se ensambla el Árbol de Sombras de React.
Detalles Adicionales
-
Las operaciones (creación de Nodo de Sombra de React, creación de relaciones padre-hijo entre Nodos de Sombra de React) son operaciones síncronas y seguras para hilos que se ejecutan desde React (JavaScript) hacia el renderizador (C++), generalmente en el hilo de JavaScript.
-
El Árbol de Elementos de React (y sus Nodos de Elemento de React constituyentes) no existen indefinidamente. Es una representación temporal materializada por "fibers" en React. Cada "fiber" que representa un componente de anfitrión almacena un puntero de C++ al Nodo de Sombra de React, posibilitado por JSI. Aprende más sobre "fibers" en este documento.
-
El React Shadow Tree es inmutable. Para actualizar cualquier React Shadow Node, el renderizador crea un nuevo React Shadow Tree. Sin embargo, el renderizador proporciona operaciones de clonación para optimizar las actualizaciones de estado (ver Actualizaciones de estado en React para más detalles).
En el ejemplo anterior, el resultado de la fase de renderizado se ve así:

Tras completarse el React Shadow Tree, el renderizador activa un commit del React Element Tree.
Fase 2. Commit

La fase de commit consta de dos operaciones: Cálculo de diseño y Promoción de árbol.
- Cálculo de diseño: Calcula la posición y tamaño de cada React Shadow Node. En React Native, esto implica invocar Yoga para determinar el diseño de cada nodo. El cálculo requiere los estilos de cada React Shadow Node (originados en un React Element en JavaScript) y las restricciones de diseño de la raíz del React Shadow Tree, que determinan el espacio disponible.

- Promoción de árbol (Árbol nuevo → Árbol siguiente): Promueve el nuevo React Shadow Tree como el "siguiente árbol" a montar. Esto indica que el nuevo árbol contiene toda la información para montarse y representa el estado más reciente del React Element Tree. El "siguiente árbol" se monta en el próximo ciclo del hilo de UI.
Detalles Adicionales
-
Estas operaciones se ejecutan asíncronamente en un hilo en segundo plano.
-
La mayoría del cálculo de diseño ocurre en C++. Sin embargo, el cálculo para componentes como
TextoTextInputdepende de la plataforma host y debe calcularse en su capa. Para esto, Yoga invoca funciones definidas en la plataforma host.
Fase 3. Mount

El montaje transforma el React Shadow Tree (que ahora contiene datos de diseño) en un Host View Tree con píxeles renderizados. Recordemos que el React Element Tree se ve así:
<View>
<Text>Hello, World</Text>
</View>
El renderizador crea una Host View correspondiente para cada React Shadow Node. Por ejemplo:
- Android:
android.view.ViewGrouppara<View>yandroid.widget.TextViewpara<Text> - iOS:
UIViewcon texto poblado medianteNSLayoutManagerCada vista host se configura con las props de su React Shadow Node y la información de diseño calculada.

En detalle, el montaje incluye tres pasos:
-
Tree Diffing (Diferenciación de árboles): Este paso calcula la diferencia entre el "árbol renderizado previamente" y el "siguiente árbol" completamente en C++. El resultado es una lista de operaciones de mutación atómicas que se realizarán en las vistas host (por ejemplo,
createView,updateView,removeView,deleteView, etc). Este paso también es donde el React Shadow Tree se aplana para evitar crear vistas host innecesarias (ver Aplanamiento de Vistas para detalles sobre este algoritmo). -
Promoción del árbol (Siguiente árbol → Árbol renderizado): Este paso promueve atómicamente el "siguiente árbol" a "árbol previamente renderizado" para que la fase de montaje calcule una diferencia con respecto al árbol correcto.
-
Montaje de Vistas: Este paso aplica las operaciones de mutación atómica sobre las vistas del host correspondientes. Se ejecuta en la plataforma host en el hilo de UI.
Detalles Adicionales
-
Las operaciones se ejecutan sincrónicamente en el hilo de UI. Si la fase de commit ocurre en un hilo en segundo plano, el montaje se programa para el siguiente "tick" del hilo de UI. Si el commit ocurre en el hilo de UI, el montaje se ejecuta sincrónicamente en el mismo hilo.
-
La programación, implementación y ejecución de la fase de montaje dependen en gran medida de la plataforma host. Por ejemplo, la arquitectura del renderizador en la capa de montaje actualmente difiere entre Android e iOS.
-
Durante el renderizado inicial, el "árbol previamente renderizado" está vacío. Por lo tanto, la comparación de árboles resultará en operaciones de mutación que solo incluyen crear vistas, establecer props y agregar vistas entre sí. La comparación de árboles adquiere mayor importancia para el rendimiento al procesar Actualizaciones de Estado de React.
-
En pruebas de producción actuales, un Árbol Sombra de React típicamente contiene 600-1000 Nodos Sombra de React (antes del aplanamiento de vistas), reduciéndose a ~200 nodos después del aplanamiento. En aplicaciones para iPad o escritorio, esta cantidad puede aumentar 10 veces.
Actualizaciones de Estado de React
Exploremos cada fase del pipeline de renderizado cuando se actualiza el estado de un Árbol de Elementos React. Supongamos que renderizaste este componente inicialmente:
function MyComponent() {
return (
<View>
<View
style={{backgroundColor: 'red', height: 20, width: 20}}
/>
<View
style={{backgroundColor: 'blue', height: 20, width: 20}}
/>
</View>
);
}
Aplicando lo descrito en Renderizado Inicial, se crearían los siguientes árboles:

Observa que Nodo 3 mapea a una vista host con fondo rojo, y Nodo 4 a una con fondo azul. Supón que por una actualización de estado, el fondo del primer <View> anidado cambia de 'red' a 'yellow'. Así podría verse el nuevo Árbol de Elementos React:
<View>
<View
style={{backgroundColor: 'yellow', height: 20, width: 20}}
/>
<View
style={{backgroundColor: 'blue', height: 20, width: 20}}
/>
</View>
¿Cómo procesa React Native esta actualización?
Al ocurrir una actualización de estado, el renderizador debe actualizar conceptualmente el Árbol de Elementos React para modificar las vistas host ya montadas. Pero para garantizar seguridad en hilos, ambos árboles (Elementos React y Sombra React) deben ser inmutables. Esto implica que en lugar de mutar los árboles actuales, React debe crear nuevas copias que incorporen los nuevos props, estilos e hijos.
Exploremos cada fase del pipeline durante una actualización de estado.
Fase 1. Render

Cuando React crea un nuevo Árbol de Elementos React que incorpora el nuevo estado, debe clonar cada Elemento React y Nodo Sombra afectado por el cambio. Tras la clonación, se confirma (commit) el nuevo Árbol Sombra React.
El renderizador de React Native utiliza compartición estructural para minimizar la sobrecarga de la inmutabilidad. Al clonar un Elemento React para incluir el nuevo estado, se clona cada elemento en la ruta hasta la raíz. React solo clona un Elemento React si requiere actualizar sus props, estilo o hijos. Los elementos inalterados se comparten entre los árboles antiguo y nuevo.
En el ejemplo anterior, React crea el nuevo árbol mediante estas operaciones:
-
CloneNode(Nodo 3,
{backgroundColor: 'yellow'}) → Nodo 3' -
CloneNode(Nodo 2) → Nodo 2'
-
AppendChild(Nodo 2', Nodo 3')
-
AppendChild(Nodo 2', Nodo 4)
-
CloneNode(Nodo 1) → Nodo 1'
-
AppendChild(Nodo 1', Nodo 2')
Tras estas operaciones, Nodo 1' representa la raíz del nuevo Árbol de Elementos de React. Asignemos T al "árbol previamente renderizado" y T' al "nuevo árbol":

Observa cómo T y T' comparten Nodo 4. Este uso compartido estructural mejora el rendimiento y reduce el consumo de memoria.
Fase 2. Commit

Después de que React crea el nuevo Árbol de Elementos de React y Árbol de Sombra de React, debe confirmarlos.
-
Cálculo de diseño: Similar al cálculo de diseño durante el Renderizado inicial. Una diferencia importante es que el cálculo de diseño puede provocar la clonación de Nodos de Sombra de React compartidos. Esto ocurre porque si el padre de un Nodo de Sombra de React compartido sufre un cambio de diseño, el diseño del nodo compartido también puede verse afectado.
-
Promoción del árbol (Árbol nuevo → Siguiente árbol): Similar a la Promoción del árbol durante el Renderizado inicial.
Fase 3. Mount

-
Promoción del árbol (Siguiente árbol → Árbol renderizado): Este paso promueve atómicamente el "siguiente árbol" a "árbol previamente renderizado" para que la fase de montaje calcule una diferencia con respecto al árbol correcto.
-
Cálculo de diferencias: Este paso calcula la diferencia entre el "árbol previamente renderizado" (T) y el "siguiente árbol" (T'). El resultado es una lista de operaciones de mutación atómicas que se aplicarán a las vistas del host.
- En el ejemplo anterior, las operaciones consisten en:
UpdateView(**Node 3**, {backgroundColor: 'yellow'}) - La diferencia se puede calcular entre cualquier árbol montado actualmente y cualquier nuevo árbol. El renderizador puede omitir algunas versiones intermedias del árbol.
- En el ejemplo anterior, las operaciones consisten en:
-
Montaje de vistas: Este paso aplica las operaciones de mutación atómicas a las vistas del host correspondientes. En el ejemplo anterior, solo se actualizará el
backgroundColorde View 3 (a amarillo).

Actualizaciones de estado del renderizador de React Native
Para la mayoría de la información en el Árbol de Sombra, React es el único propietario y fuente única de verdad. Todos los datos se originan en React y existe un flujo unidireccional de datos.
Sin embargo, existe una excepción importante: los componentes en C++ pueden contener estado que no está expuesto directamente a JavaScript, y JavaScript no es la fuente de verdad. Este Estado de C++ está controlado por C++ y la Plataforma Host. Generalmente, esto solo es relevante si desarrollas un Componente Host complejo que requiera Estado de C++. La gran mayoría de Componentes Host no necesitan esta funcionalidad.
Por ejemplo, ScrollView usa este mecanismo para informar al renderizador sobre el desplazamiento actual. La actualización se desencadena desde la plataforma host, específicamente desde la vista host que representa el componente ScrollView. Esta información sobre desplazamiento se usa en APIs como measure. Como esta actualización proviene de la plataforma host y no afecta al Árbol de Elementos de React, estos datos de estado se almacenan en el Estado de C++.
Conceptualmente, las actualizaciones de Estado en C++ son similares a las Actualizaciones de Estado de React descritas anteriormente, con dos diferencias importantes:
-
Omiten la "fase de render" (render phase) ya que React no participa.
-
Las actualizaciones pueden originarse y ejecutarse en cualquier hilo, incluido el hilo principal.
Fase 2. Commit

Al realizar una actualización de Estado en C++, un bloque de código solicita la actualización de un ShadowNode (N) para establecer el Estado en C++ al valor S. El renderizador de React Native intentará repetidamente obtener la última versión confirmada de N, clonarla con el nuevo estado S, y confirmar N’ en el árbol. Si React u otra actualización de Estado en C++ ha realizado otra confirmación durante este proceso, la operación fallará y el renderizador reintentará la actualización varias veces hasta lograr una confirmación exitosa. Esto previene colisiones y condiciones de carrera en la fuente de verdad.
Fase 3. Mount

La Fase de Montaje es prácticamente idéntica a la Fase de Montaje de las Actualizaciones de Estado de React. El renderizador aún necesita recalcular el diseño, realizar un diff del árbol, etc. Consulta las secciones anteriores para más detalles.