<h2>Entendendo o Reconciler: O Coração do React</h2>
<p>O Reconciler é o mecanismo que React utiliza para determinar quais mudanças devem ser aplicadas ao DOM. Quando você atualiza o estado de um componente, o React não simplesmente reescreve tudo na tela. Em vez disso, ele compara a árvore anterior (virtual) com a nova, identificando apenas as diferenças. Esse processo é chamado de <em>reconciliação</em> ou <em>diffing</em>.</p>
<p>Antes do React Fiber (versão 16+), o algoritmo de reconciliação era síncrono e bloqueante — se você tivesse uma árvore grande de componentes, o navegador congelava enquanto React calculava as mudanças. O React Fiber resolveu isso introduzindo unidades de trabalho pequenas e preemptíveis, permitindo que o navegador interrompa o trabalho para tarefas de alta prioridade como eventos de usuário ou animações.</p>
<pre><code class="language-javascript">// Exemplo simples: como o React faz diffing
function reconcile(oldVNode, newVNode) {
// Se tipos são diferentes, substitui toda a árvore
if (typeof oldVNode !== typeof newVNode) {
return newVNode;
}
// Se ambos são strings ou números, compara direto
if (typeof newVNode !== 'object') {
return oldVNode === newVNode ? oldVNode : newVNode;
}
// Se são objetos (componentes), compara props e filhos
if (oldVNode.type === newVNode.type) {
return {
...newVNode,
children: reconcileChildren(oldVNode.children, newVNode.children)
};
}
return newVNode;
}</code></pre>
<h2>Fiber Architecture: A Revolução Estrutural</h2>
<p>A arquitetura Fiber decompõe o trabalho em unidades chamadas <em>fibers</em>. Cada fiber representa um componente, um hook, um texto ou qualquer outro elemento na árvore. Um fiber é um objeto JavaScript com referências para seu pai (return), seus filhos (child) e seu irmão (sibling), formando uma estrutura de árvore ligada.</p>
<p>O grande ganho é a <em>interruptibilidade</em>: React pode pausar o trabalho em um fiber, salvar seu estado, permitir que o navegador execute tarefas mais urgentes e depois retomar de onde parou. Isso é possível porque o trabalho foi dividido em pequenas unidades que cabem em um <em>time slice</em> (janela de tempo do navegador, geralmente 5ms).</p>
<pre><code class="language-javascript">// Estrutura simplificada de um Fiber
const fiber = {
type: MyComponent, // Tipo do componente
key: 'unique-key', // Key para reconciliação
props: { name: 'João' }, // Props do componente
state: null, // Estado local (hooks)
// Relações na árvore
return: parentFiber, // Referência ao pai
child: childFiber, // Primeiro filho
sibling: siblingFiber, // Próximo irmão
// Rastreamento de mudanças
alternate: oldFiber, // Versão anterior para diff
effectTag: 'UPDATE', // UPDATE, PLACEMENT, DELETION
effects: [], // Effects para executar
};
// Exemplo de como React percorre a árvore de Fibers
function performUnitOfWork(fiber) {
// 1. Processa o próprio fiber
processComponent(fiber);
// 2. Se tem filho, trabalha nele primeiro (depth-first)
if (fiber.child) {
return fiber.child;
}
// 3. Se não tem filho, trata efeitos e volta
completeUnitOfWork(fiber);
// 4. Tenta o irmão
if (fiber.sibling) {
return fiber.sibling;
}
// 5. Volta para o pai
return fiber.return;
}</code></pre>
<h2>Rendering Phases: Render e Commit</h2>
<p>O React dividiu o processo de renderização em duas fases distintas: <strong>Render Phase</strong> e <strong>Commit Phase</strong>. Essa separação é crucial para entender como React implementa concorrência e por que certas otimizações funcionam.</p>
<h3>Render Phase (Assíncrona e Preemptível)</h3>
<p>Na fase de render, React constrói a nova árvore de Fibers, executa componentes, calcula diffs e marca qual trabalho precisa ser feito. <strong>Nada é aplicado ao DOM ainda</strong>. Como essa fase é preemptível, React pode pausar, abandonar e recomeçar sem problemas. É por isso que efeitos colaterais <strong>nunca devem</strong> estar no corpo do componente — o componente pode ser renderizado múltiplas vezes sem sucesso.</p>
<h3>Commit Phase (Síncrona e Irrevogável)</h3>
<p>Na fase de commit, React aplica todas as mudanças de uma vez ao DOM. Essa fase é síncrona porque queremos que o DOM chegue a um estado consistente rapidamente. Aqui também são executados os hooks como <code>useEffect</code> e <code>useLayoutEffect</code>.</p>
<pre><code class="language-javascript"></code></pre>
<h2>Prioridades e Concurrent Rendering</h2>
<p>React não trata todos os updates com a mesma urgência. Eventos de clique têm prioridade sobre atualizações de dados de fundo. O React classifica o trabalho em diferentes níveis: <code>ImmediatePriority</code>, <code>UserBlockingPriority</code>, <code>NormalPriority</code>, <code>LowPriority</code> e <code>IdlePriority</code>.</p>
<p>Quando múltiplos updates estão em fila, React trabalha primeiro nos de alta prioridade. Se um update de alta prioridade chega enquanto um de baixa prioridade está sendo renderizado, React descarta o trabalho de baixa prioridade e recomeça com o novo update. Essa decisão é feita na Render Phase justamente porque nada foi commitado ainda.</p>
<pre><code class="language-javascript">// Exemplo simplificado de priorização
const priorities = {
Immediate: 1,
UserBlocking: 2,
Normal: 3,
Low: 4,
Idle: 5
};
function scheduleUpdate(update, priority) {
const task = { update, priority, expirationTime: now() + getTimeout(priority) };
// Insere na fila ordenada por prioridade
updateQueue.push(task);
updateQueue.sort((a, b) => a.priority - b.priority);
// Trata updates de alta prioridade antes
const highPriorityTask = updateQueue[0];
processUpdate(highPriorityTask);
}</code></pre>
<h2>Conclusão</h2>
<p>Entender React Internals é fundamental para escrever código performático. O <strong>Reconciler</strong> usa diffing para identificar mudanças; a <strong>Fiber Architecture</strong> permite que React interrompa trabalhos longos em unidades pequenas; e a divisão entre <strong>Render e Commit Phases</strong> garantem que o DOM chegue a estados consistentes. Combine isso com prioridades inteligentes e você tem um framework capaz de manter 60fps mesmo em aplicações complexas. A próxima vez que escrever um componente, lembre-se: efeitos colaterais vão no <code>useEffect</code>, não no corpo da função.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=ZCuYPiUIONs" target="_blank" rel="noopener noreferrer">React Fiber Architecture - Lin Clark (Código Confex)</a></li>
<li><a href="https://react.dev/learn/render-and-commit" target="_blank" rel="noopener noreferrer">React Reconciliation - Official Documentation</a></li>
<li><a href="https://indepth.dev/posts/1007/the-how-and-why-on-reacts-usage-of-linked-list-in-fiber-to-walk-the-component-tree" target="_blank" rel="noopener noreferrer">The How and Why on React's Usage of Linked List in Fiber to Walk the Component Tree</a></li>
<li><a href="https://overreacted.io/" target="_blank" rel="noopener noreferrer">React Fiber Deep Dive - Dan Abramov's Blog</a></li>
<li><a href="https://medium.com/react-in-depth/inside-fiber-in-depth-overview-of-the-new-reconciliation-engine-in-react-e1c04700ef6e" target="_blank" rel="noopener noreferrer">Inside Fiber: an in-depth overview of the new reconciliation engine in React</a></li>
</ul>