Saltar al contenido

Fiber y el double buffering

¿Dónde guarda React el estado si los componentes son funciones sin memoria?

Al terminar vas a poder explicar

  • Describir qué campos tiene un fiber y para qué sirve cada uno
  • Explicar qué significa el puntero alternate
  • Decir en qué momento exacto el árbol workInProgress pasa a ser el actual

Tenemos un problema. Tu componente es una función que se ejecuta de arriba a abajo y termina. Cuando vuelve a ejecutarse, todas sus variables locales son nuevas. No tiene memoria. Y sin embargo useState se acuerda del valor anterior.

La respuesta es que el estado nunca estuvo en tu función. Está al lado, en una estructura que React mantiene en paralelo al árbol de componentes: el árbol de fibers.

Qué es un fiber

Un fiber es un objeto plano que representa una aparición concreta de un componente. Si renderizás <Fila /> tres veces, hay tres fibers, cada uno con su propio estado. Estos son los campos que importan:

los campos que vas a ver en el trazador
1{2  tag: "FunctionComponent",   // qué clase de nodo es3  type: Fila,                 // la función, o "div" si es un host4  key: "alfa",                // la identidad que le diste vos5 6  pendingProps: { ... },      // las props de este render7  memoizedProps: { ... },     // las del render anterior8  memoizedState: hook0,       // ← acá cuelga la cadena de hooks9 10  return: fiberPadre,         // hacia arriba11  child: primerHijo,          // hacia abajo12  sibling: siguienteHermano,  // hacia el costado13 14  alternate: fiberGemelo,     // el otro buffer15  flags: 0b000001,            // qué hacer en el commit16  lanes: 0b010,               // qué prioridad tiene el trabajo pendiente17  stateNode: nodoDelDOM       // sólo en componentes host18}

El árbol no es un árbol de arrays

Mirá los punteros: child, sibling, return. Un fiber no tiene un array de hijos. Tiene un hijo, y ese hijo tiene un hermano, que tiene otro hermano. Es una lista enlazada dentro de un árbol.

Esto no es capricho. Con un array, recorrer el árbol requiere recursión — y una recursión no se puede pausar a la mitad sin perder el stack. Con punteros, React puede guardar un solo cursor («estaba en este fiber»), soltar el hilo para que el navegador atienda un click, y retomar exactamente donde estaba.

El double buffering

Acá viene la parte que casi nadie tiene clara. React no tiene un árbol: tiene dos, y los va alternando.

  • current — el árbol que está en pantalla ahora mismo.
  • workInProgress — el que React está construyendo, en memoria, invisible.

Cada fiber apunta a su gemelo del otro árbol con alternate. Cuando React termina de construir el workInProgress, hace una sola asignación — root.current = finishedWork — y el árbol nuevo pasa a ser el actual. El viejo no se tira: queda libre para reciclarse en el próximo render.

Es la misma técnica que usan los motores gráficos: dibujás en un buffer oculto y recién después lo mostrás entero. Nadie ve un cuadro a medio dibujar.

Mirá cuándo aparece el buffer alterno, y cuándo se intercambian

AGENDADOpaso 1 / 96
Traza
Cadena de hooks · <>

Sin hooks en este paso.

Árbol de fibers

  • <HostRoot>

Salida

Nada en el host todavía. React no commiteó ningún cambio.

createRoot().render()

Montaje inicial. No hay árbol previo, así que todo se va a crear desde cero.

VER EL CÓDIGO QUE SE ESTÁ TRAZANDO
1function Contador() {2  const [n, setN] = useState(0);3 4  return (5    <div>6      <p>Valor: {n}</p>7      <button onClick={() => setN(n + 1)}>sumar 1</button>8    </div>9  );10}

Con el foco acá: ← → un paso · espacio reproduce · Inicio/Fin van a los extremos.

Fijate en dos momentos de esa traza. En el montaje aparece createWorkInProgress diciendo que no existía buffer alterno — porque es la primera vez. En el segundo render, el mismo paso dice que lo reutiliza. Ahí está el reciclado: React deja de asignar objetos nuevos y alterna entre dos.

Y al final de cada ciclo vas a ver root.current = finishedWork. Ese es el instante del intercambio. Un puntero. Nada más.

Antes de seguir · predecí

Durante la fase de render, mientras React construye el workInProgress, ¿qué se está viendo en la pantalla?

Lo que te llevás

Tu estado vive en fiber.memoizedState, no en tu función. El árbol se recorre con punteros para poder pausarse. Y hay dos árboles alternándose, lo que permite construir en privado y publicar de golpe. En la próxima lección vamos a ver esas dos etapas — construir y publicar — con nombre y apellido.

Antes de marcarla, comprobá

  • ¿Podés explicar describir qué campos tiene un fiber y para qué sirve cada uno?
  • ¿Podés explicar explicar qué significa el puntero alternate?
  • ¿Podés explicar decir en qué momento exacto el árbol workInProgress pasa a ser el actual?