O useSyncExternalStore permite que um componente leia dados que residem fora do React sem o risco de falhas visuais que a renderização concorrente pode introduzir. Ele substitui o antigo padrão de trazer valores externos para o estado local com useEffect, um padrão que pode causar "tearing" – partes da UI exibindo valores diferentes durante a mesma renderização.
Por que o antigo padrão falha sob concorrência
Antes do React 18, a receita comum era:
const [value, setValue] = useState(initial);
useEffect(() => {
const unsubscribe = externalSource.subscribe(v => setValue(v));
return unsubscribe;
}, []);
O efeito é executado após o componente ter sido renderizado. Quando o renderizador concorrente do React decide pausar, abortar ou repetir uma renderização, o efeito pode ser disparado em um ponto diferente da UI que lê o estado. O resultado é uma incompatibilidade: um componente pode ter lido o valor antigo, outro o novo, e a tela mostra brevemente dados inconsistentes. Esse "tearing" é inofensivo em um mundo puramente síncrono, mas torna-se um bug visível quando o React renderiza múltiplas versões da UI em paralelo.
Como o useSyncExternalStore resolve o problema
O hook requer dois callbacks:
- subscribe – registra um ouvinte e retorna uma função que o remove.
- getSnapshot – retorna o valor atual da fonte externa.
O React chama o subscribe quando o componente é montado e o descarta no unmount. Durante cada renderização, ele invoca o getSnapshot e garante que todos os componentes que utilizam o mesmo store externo leiam exatamente o mesmo snapshot. Como a leitura ocorre dentro da fase de renderização, o renderizador pode coordenar as atualizações em toda a árvore, eliminando o tearing.
Bibliotecas como Zustand e Redux já envolvem seus stores com este hook, e é por isso que elas funcionam nativamente com os recursos concorrentes do React 18.
Regras para evitar o mau funcionamento do hook
- Retorne apenas o que o componente precisa – um objeto grande força o React a comparar estruturas profundas em cada atualização. Um snapshot restrito mantém a detecção de mudanças barata.
- Preserve a identidade referencial – se o valor externo não mudou, o getSnapshot deve retornar a mesma referência de objeto. Retornar um novo objeto a cada chamada dispara um loop de renderização infinito, pois o React detecta uma mudança em cada renderização.
- Limite o uso a fontes externas – o estado local do componente deve pertencer ao
useStateouuseReducer. Usar o hook de store externo para valores puramente internos adiciona uma indireção desnecessária.
Quando recorrer ao useSyncExternalStore
- Envolvendo APIs do navegador (tamanho da janela, status de rede online, media queries).
- Conectando um store JavaScript puro que não conhece o React.
- Substituindo o prop-drilling por uma fonte global de apenas leitura à qual muitos componentes se inscrevem.
O contra-argumento
O padrão useState + useEffect ainda funciona para dados simples e que mudam com pouca frequência, especialmente quando uma aplicação não habilita recursos concorrentes. É uma abordagem de nível mais baixo que alguns desenvolvedores consideram mais fácil de raciocinar, pois a lógica de inscrição reside explicitamente no efeito. No entanto, a compensação é o risco de tearing assim que a renderização concorrente é ativada. Para projetos que já utilizam as novas capacidades do React 18, a segurança extra do useSyncExternalStore supera o mínimo de boilerplate adicional.
O que observar a seguir
- Verifique se o getSnapshot do seu store retorna uma referência estável; um
console.lográpido da referência durante o desenvolvimento pode expor a recriação acidental de objetos. - Mantenha a função de inscrição leve – o trabalho pesado deve ocorrer dentro da fonte externa, não no callback passado ao React.
- Teste os componentes no modo concorrente do React (por exemplo, usando
actcomReactDOM.createRoot) para confirmar que nenhum tearing apareça.
Uma demonstração ao vivo mostra o hook em ação, sincronizando um contador simples armazenado fora do React e atualizando múltiplos componentes sem falhas visuais. A demonstração está disponível em https://usesyncexternalstore.vercel.app/. O código-fonte está no GitHub, e um texto mais detalhado explica os detalhes da implementação.
Conclusão: Em um mundo onde o React pode renderizar partes da UI fora de ordem, o useSyncExternalStore é a ponte confiável entre dados externos e a renderização de componentes. Ele preserva a consistência visual, escala para stores globais e já está integrado em bibliotecas populares de gerenciamento de estado. Adote-o sempre que precisar ler um estado que não seja do React, e mantenha os snapshots pequenos e estáveis para colher todos os seus benefícios.
