Montagem cliente ou hidratação
A decisão começa no contentor recebido. Se a aplicação cliente começa num nó vazio sem HTML React pré-renderizado, createRoot cria a raiz e root.render apresenta a árvore. Se o contentor já contém HTML produzido por React no servidor, hydrateRoot liga a árvore ao conteúdo existente.
Não é necessário chamar novamente a API para cada mudança de estado. A hidratação pressupõe que a primeira saída cliente corresponde à saída do servidor. Usar uma API de montagem como substituto indiferente pode recriar conteúdo que se pretendia conservar.
Num framework, o arranque pode já ser responsabilidade da infraestrutura; não acrescentes uma segunda raiz sem compreender esse contrato.
Conservar o primeiro snapshot
No exemplo, initialPrice é uma string de apresentação que o anfitrião conserva desde a renderização do servidor. PriceReview começa com esse valor e só muda depois de uma ação. Se o cliente substituir o valor por outro preço antes de hidratar, passa a produzir uma saída inicial diferente.
Datas calculadas separadamente, dados novos ou ramos condicionais baseados em window também podem criar diferenças. A correção depende da causa: conservar o snapshot inicial e programar uma atualização posterior é uma estratégia quando o requisito permite.
O exemplo não fornece o servidor nem a codificação segura de dados num documento HTML; esses contratos pertencem ao anfitrião.
Recuperação não substitui reconciliação
React recupera de alguns erros de hidratação, mas a API não garante corrigir todas as diferenças de atributos. onRecoverableError permite observar erros recuperados e informação da árvore. O destino dessa informação deve corresponder à política de observabilidade da aplicação. suppressHydrationWarning é uma exceção limitada a um nível, útil para uma diferença inevitável e delimitada; não é uma reparação recursiva nem corrige texto divergente.
Chamar root.render antes de terminar a hidratação também não é um atalho inofensivo: pode limpar o HTML existente e mudar a raiz inteira para renderização cliente. Primeiro reconcilia a saída e a ordem de arranque.
Server Components e dependências de módulos
React Server Components usam um ambiente de avaliação separado, que pode correr durante o build ou por pedido. A diretiva use client marca uma fronteira na árvore de dependências de módulos: o módulo e os seus imports transitivos pertencem ao ramo cliente.
A posição visual não basta para decidir o ambiente de avaliação. Um Server Component pode criar JSX e passá-lo como children a um Client Component que não importa esse módulo. Por isso, ler apenas a hierarquia JSX pode produzir um diagnóstico errado.
A diretiva deve estar no início do ficheiro, antes dos imports. Esta aula interpreta o contrato React; não apresenta uma implementação completa de routing ou bundling de um framework.
Transportar dados suportados
As props que atravessam de Server para Client Components precisam de valores suportados pela serialização React. Um objeto simples com strings, números e booleanos pode representar uma fatura sem transportar a instância de uma classe de domínio e os seus métodos.
A lista suportada não se reduz a JSON: inclui também tipos documentados como Date, Map, Set, elementos JSX e Server Functions. Isso não autoriza transportar qualquer closure local ou classe arbitrária. Se a interação só precisa de id, total e approved, um objeto simples torna o contrato explícito e a lógica local pode ser definida no módulo cliente. A fronteira de módulos não concede permissões de negócio.
HTML bruto e confiança no conteúdo
dangerouslySetInnerHTML substitui conteúdo por HTML bruto e exige uma decisão de confiança. Uma string guardada numa base de dados pode continuar a conter conteúdo introduzido por terceiros. Nem key, Suspense nem a origem num Server Component sanitizam essa string.
Se a interface só precisa de mostrar texto, usa o caminho de texto. Se necessita de HTML, conserva uma política explícita de conteúdo confiável e sanitizado e aplica-a antes dessa fronteira. Mesmo quando Trusted Types está em uso, a política que cria TrustedHTML continua responsável pelos dados aceites.
O objetivo é identificar onde o conteúdo deixa de ser apenas dados e passa a ser interpretado como HTML.
Aceitação da entrega e limites de versão
Na aceitação, regista se o produto usa montagem cliente, HTML de servidor com hidratação ou uma integração RSC. Verifica o contrato de dados inicial e observa interações posteriores sem confundir o botão Mark for refresh com um pedido real: no exemplo, só altera texto local.
Para implementações próprias de bundlers, há outra distinção: Server Components são estáveis em React 19, mas as APIs subjacentes usadas por bundlers e frameworks podem mudar entre versões menores. A documentação recomenda fixar uma versão específica nesse contexto.
Uma atualização deve respeitar a integração suportada, os dados transportados e a correspondência inicial; a existência de HTML visível não demonstra todos esses contratos.
// Shared component: the server must render this same initial output.
import {useState} from 'react';
import {hydrateRoot} from 'react-dom/client';
export function PriceReview({initialPrice}) {
const [price, setPrice] = useState(initialPrice);
return <section>
<h2>Price review</h2>
<p>{price}</p>
<button type="button" onClick={() => setPrice('Pending refresh')}>
Mark for refresh
</button>
</section>;
}
// Browser bootstrap called by the host, after its DOM is available.
// container contains server React HTML for the same PriceReview/initialPrice.
// initialPrice is the same display string used on the server.
export function attachPriceReview(container, initialPrice, reportRecovery) {
return hydrateRoot(container, <PriceReview initialPrice={initialPrice} />, {
onRecoverableError(error, info) {
reportRecovery(error, info);
}
});
}O anfitrião fornece o contentor, a mesma string de preço usada no servidor e um callback de observabilidade. O primeiro render conserva essa string; o clique posterior muda apenas o texto local para Pending refresh. Não há pedido de atualização implementado, serialização HTML de dados nem framework RSC neste exemplo.
Armadilhas comuns
Usar hydrateRoot num contentor vazio; recalcular dados diferentes antes do primeiro render; tratar suppressHydrationWarning como reparação recursiva; confundir filhos visuais com imports; transportar classes arbitrárias; confiar em HTML apenas porque veio da base de dados.
Tópicos relacionados: Componentes, props e renderização pura · Estrutura do estado e identidade dos componentes · Testar comportamentos e delimitar a evidência
A hidratação liga comportamento a uma saída inicial que deve corresponder. Fronteiras servidor/cliente pertencem ao contrato de módulos e dados; não dispensam autorização ou confiança explícita no conteúdo. Usa o framework compatível e a versão suportada, sem inferir estabilidade de APIs internas.
Referência: Initial hydration contract · React 19.3.0; JSX