<h2>React Fiber: Arquitetura Interna, Reconciliation e Rendering Phases</h2>
<p>React Fiber é a reimplementação do mecanismo de rendering do React, introduzida na versão 16. Antes do Fiber, o React usava uma abordagem de pilha de chamadas que renderizava a árvore de componentes de forma síncrona, bloqueando a thread principal e impedindo que o navegador processasse eventos, animações ou outras tarefas importantes. O Fiber resolve esse problema dividindo o trabalho de rendering em pequenas unidades chamadas de fibers, que podem ser pausadas, retomadas e priorizadas.</p>
<p>A motivação central do Fiber é permitir incremental rendering — a capacidade de dividir o trabalho de rendering em várias frames, priorizando tarefas mais urgentes e deixando tarefas menos críticas para depois. Isso resulta em uma experiência de usuário significativamente melhor, especialmente em dispositivos com menor poder computacional ou durante períodos de alta atividade.</p>
<h2>O Modelo Mental do Fiber</h2>
<h3>O que é um Fiber?</h3>
<p>Um fiber é um objeto JavaScript que representa uma unidade de trabalho. Cada componente na árvore do React tem um fiber correspondente. Um fiber contém informações sobre o componente, seu estado, props, filhos e referências para fibers relacionados. Diferentemente da abordagem anterior baseada em pilha, fibers formam uma estrutura ligada (linked structure) que permite ao React pausar, resumir e descartar trabalho sem perder o estado.</p>
<pre><code class="language-javascript">// Estrutura simplificada de um Fiber
const fiber = {
// Tipo do componente
type: MyComponent,
// Props e estado
props: { name: 'John' },
state: { count: 0 },
// Referências para outros fibers
parent: parentFiber,
child: childFiber,
sibling: siblingFiber,
// Trabalho associado
effectTag: 'UPDATE', // 'PLACEMENT', 'UPDATE', 'DELETION'
effects: [],
// Instância do componente (class components)
instance: componentInstance,
// Hooks e estado funcional
memoizedState: null,
// Versão anterior do fiber (para comparação)
alternate: previousVersionFiber
};</code></pre>
<p>A estrutura de linked fibers é fundamental porque permite que React navegue pela árvore sem depender da pilha de chamadas. A referência <code>alternate</code> é particularmente importante — ela aponta para a versão anterior do fiber, permitindo que React compare o estado anterior com o novo durante a reconciliação.</p>
<h3>Por que uma Linked Structure?</h3>
<p>Quando o React precisava renderizar uma árvore usando recursão (na abordagem anterior), a pilha de chamadas do JavaScript acumulava todas as chamadas recursivas. Se uma renderização demorasse muito (digamos, alguns segundos), nada mais poderia executar na thread principal — nenhum evento seria processado, nenhuma animação seria desenhada. A linked structure elimina essa dependência da pilha e permite que React controle quando pausar e retomar o trabalho.</p>
<h2>Fases de Rendering: Render e Commit</h2>
<p>React divide o processo de rendering em duas fases distintas: <strong>render phase</strong> e <strong>commit phase</strong>. Compreender essa divisão é essencial para entender Fiber.</p>
<h3>Render Phase (Fase de Renderização)</h3>
<p>A render phase é onde React executa a reconciliação — comparando a nova árvore com a anterior, determinando quais componentes precisam de atualizações e criando uma lista de efeitos a serem executados. Durante essa fase, React pode pausar, descartar ou retomar o trabalho a qualquer momento. É seguro repetir essa fase múltiplas vezes porque nenhuma alteração real é feita ainda.</p>
<pre><code class="language-javascript">// Exemplo: componente que pode ter sua renderização pausada/retomada
function Counter() {
const [count, setCount] = React.useState(0);
// Este código executa durante a render phase
console.log('Rendering component with count:', count);
const expensiveCalculation = () => {
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += Math.sqrt(i);
}
return result;
};
// Este cálculo pesado pode ser entrecortado
const value = expensiveCalculation();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}</code></pre>
<p>Durante a render phase, React não atualiza o DOM ou chama efeitos colaterais (como <code>useEffect</code>). Se você tentar acessar <code>document.getElementById()</code> ou modificar referências diretas durante o render, o comportamento será impredizível porque a fase pode ser pausada ou repetida.</p>
<h3>Commit Phase (Fase de Commit)</h3>
<p>Após a render phase estar completa, React entra na commit phase — é aqui que as mudanças são realmente aplicadas ao DOM. Diferentemente da render phase, a commit phase é <strong>síncrona e não pode ser interrompida</strong>. React precisa garantir que toda a árvore de DOM seja atualizada de forma consistente em uma única operação.</p>
<pre><code class="language-javascript">function DataFetcher() {
const [data, setData] = React.useState(null);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
// Este código é executado APÓS a commit phase
console.log('Commit phase completed, now fetching data');
fetch('/api/data')
.then(res => res.json())
.then(json => {
setData(json);
setLoading(false);
});
}, []);
return loading ? <p>Loading...</p> : <pre>{JSON.stringify(data)}</pre>;
}</code></pre>
<p>A separação entre render e commit phases é o que permite que React priorize trabalho. Se uma atualização urgente chegar (como resposta a um clique do usuário), React pode pausar uma renderização de baixa prioridade (como atualizar uma lista grande) e processar o clique primeiro.</p>
<h2>Reconciliation: O Algoritmo de Comparação</h2>
<h3>O Algoritmo Reconciliation</h3>
<p>A reconciliação é o processo de comparação entre a árvore anterior (representada pelos fibers <code>alternate</code>) e a nova árvore (a que seria renderizada agora). O objetivo é identificar quais nós sofreram mudanças e precisam ser atualizados no DOM.</p>
<p>O React usa heurísticas inteligentes para tornar a reconciliação eficiente:</p>
<ol>
<li><strong>Elementos de tipos diferentes produzem árvores diferentes</strong>: Se o tipo do elemento muda (ex: <code><div></code> para <code><span></code>), React descarta a árvore antiga e cria uma nova.</li>
</ol>
<ol>
<li><strong>Keys estáveis</strong>: Quando renderizando listas, adicionar keys (chaves) ajuda React a identificar qual item é qual, mesmo que sua posição mude.</li>
</ol>
<ol>
<li><strong>Heurística de profundidade</strong>: React não compara fibers em profundidades diferentes — compara apenas fibers no mesmo nível.</li>
</ol>
<pre><code class="language-javascript"></code></pre>
<h3>Comparação de Fibers</h3>
<p>Quando React entra na render phase, ele compara cada fiber com seu <code>alternate</code> (versão anterior). Se não há <code>alternate</code>, é uma nova inserção. Se há <code>alternate</code> mas as props ou estado mudaram, é uma atualização. Se há <code>alternate</code> mas o tipo mudou, é uma exclusão seguida de uma inserção.</p>
<pre><code class="language-javascript">// Demonstração de como React rastreia mudanças
function Profile({ userId, showBio }) {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
// Renderização é pausável aqui
fetch(/api/users/${userId})
.then(r => r.json())
.then(setUser);
}, [userId]);
if (!user) return <p>Loading...</p>;
return (
<div>
<h1>{user.name}</h1>
{/ Mudanças nas props (showBio) causam re-rendering /}
{showBio && <p>{user.bio}</p>}
{/ React compara esta props com a versão anterior /}
<img src={user.avatar} alt={user.name} />
</div>
);
}
// Quando showBio muda de true para false:
// 1. Render phase: React determina que <p> precisa ser removido
// 2. Commit phase: O <p> é removido do DOM
// Tudo sem re-renderizar o componente inteiro</code></pre>
<h2>Priorização e Scheduling: Como React Organiza o Trabalho</h2>
<h3>Níveis de Prioridade</h3>
<p>React classifica atualizações em diferentes níveis de prioridade. Atualizações de cliques de usuários têm prioridade alta, enquanto atualizações de dados em background têm prioridade baixa. O scheduler do React observa se há tempo disponível na thread principal e processa trabalhos de baixa prioridade apenas quando não há trabalho de alta prioridade pendente.</p>
<pre><code class="language-javascript">// Exemplo usando startTransition (React 18+)
function SearchUsers() {
const [query, setQuery] = React.useState('');
const [results, setResults] = React.useState([]);
const [isPending, setIsPending] = React.useState(false);
const handleSearch = (e) => {
const value = e.target.value;
// Atualização urgente: atualizar o input imediatamente
setQuery(value);
// Atualização não urgente: buscar e atualizar resultados
// Pode ser interrompida se o usuário digitar novamente
React.startTransition(() => {
// Simulação de busca pesada
const filtered = largeDataset.filter(user =>
user.name.includes(value)
);
setResults(filtered);
});
};
return (
<div>
<input
value={query}
onChange={handleSearch}
placeholder="Search..."
/>
{isPending && <p>Searching...</p>}
<ul>
{results.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}</code></pre>
<p>Nesse exemplo, a atualização do <code>query</code> é processada imediatamente (alta prioridade), enquanto a filtragem dos <code>results</code> é uma transição (baixa prioridade) e pode ser interrompida. Se o usuário digitar outra letra, React descarta o trabalho anterior de filtragem e começa novamente com a nova query — sem bloquear o input.</p>
<h3>Time Slicing</h3>
<p>Time slicing é a técnica que permite que React interrompa o trabalho de render phase em pequenos intervalos, cedendo tempo para o navegador executar outras tarefas. React usa <code>requestIdleCallback</code> (ou um polyfill) para detectar quando há tempo disponível na thread principal.</p>
<pre><code class="language-javascript">// Este componente renderiza uma lista grande
function LargeList({ items }) {
console.time('render');
// Mesmo com muitos itens, a renderização não bloqueia a UI
// porque React a divide em chunks usando time slicing
const renderedItems = items.map(item => (
<div key={item.id} style={{ padding: '10px', border: '1px solid gray' }}>
<h3>{item.title}</h3>
<p>{item.description}</p>
{/ React pode pausar aqui para processar eventos /}
</div>
));
console.timeEnd('render');
return <div>{renderedItems}</div>;
}
// Uso com 10.000 itens não trava a UI
function App() {
const items = Array.from({ length: 10000 }, (_, i) => ({
id: i,
title: Item ${i},
description: Description for item ${i}
}));
return <LargeList items={items} />;
}</code></pre>
<p>React não renderiza todos os 10.000 itens de uma vez. Em vez disso, ele renderiza alguns, cede controle para o navegador processar eventos ou pintar na tela, depois volta e renderiza mais alguns.</p>
<h2>Conclusão</h2>
<p>Fiber é a arquitetura que tornou React verdadeiramente responsivo e capaz de lidar com interfaces complexas sem travar. Os três pilares para dominar Fiber são: (1) <strong>entender que fibers são objetos JavaScript que formam uma linked structure</strong>, permitindo que React controle quando pausar e retomar o trabalho; (2) <strong>separar mentalmente render phase (pausável, sem efeitos colaterais) de commit phase (síncrona, onde mudanças são aplicadas)</strong>, e (3) <strong>reconhecer que reconciliation é um algoritmo de comparação inteligente</strong> que usa heurísticas como keys estáveis e tipos de elementos para minimizar trabalho desnecessário.</p>
<p>Com esse conhecimento, você entenderá por que certas práticas (como usar index como key) prejudicam performance, e poderá escrever código React mais eficiente e previsível.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://github.com/acdlite/react-fiber-architecture" target="_blank" rel="noopener noreferrer">React Fiber Architecture - Andrew Clark (GitHub)</a></li>
<li><a href="https://react.dev/learn/render-and-commit" target="_blank" rel="noopener noreferrer">React Documentation: Reconciliation</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: in-depth overview of the new reconciliation engine</a></li>
<li><a href="https://www.freecodecamp.org/news/react-fiber-how-the-internals-work/" target="_blank" rel="noopener noreferrer">The Beginner's Guide to React Fiber</a></li>
<li><a href="https://react.dev/reference/react/useTransition" target="_blank" rel="noopener noreferrer">React 18 Transitions Documentation</a></li>
</ul>
<p><!-- FIM --></p>