Hydration Failed no Next.js: O Que Causa e Como Resolver do Jeito Certo
Se você trabalha com React moderno e Next.js, provavelmente já encontrou esse erro:
Hydration failed because the initial UI does not match what was rendered on the server.Ou então:
Text content does not match server-rendered HTML.E honestamente?
Esse é um dos erros mais irritantes do ecossistema React moderno.
Porque muitas vezes:
a aplicação aparentemente funciona
o erro aparece aleatoriamente
o comportamento muda entre ambiente local e produção
o stack trace não ajuda muito
E pior: muita gente resolve isso errado.
Coloca:
suppressHydrationWarning
dynamic import aleatório
useEffect em tudo
Sem entender o problema real.
Neste guia vamos entender:
o que é hydration
por que o erro acontece
como identificar a causa
soluções corretas
erros comuns
boas práticas
arquitetura moderna no Next.js
Tudo de forma prática.
O Que é Hydration?
Antes de resolver o erro: precisamos entender hydration.
No React moderno com SSR: o HTML é gerado primeiro no servidor.
Depois: o React no navegador “assume” aquele HTML.
Esse processo se chama: Hydration.
Fluxo Simplificado
Servidor gera HTML
↓
HTML chega no navegador
↓
React conecta eventos e estado
↓
Página vira interativa
Esse processo melhora:
SEO
performance
carregamento inicial
O Problema
O erro acontece quando:
HTML gerado no servidor
é diferente do:
HTML renderizado no cliente
Ou seja: o React compara os dois resultados e percebe inconsistência.
Resultado: Hydration Failed.
Exemplo Clássico do Problema
export default function Home() {
return (
<div>
{new Date().toLocaleTimeString()}
</div>
)
}Parece inocente.
Mas aqui existe um problema grave.
O Que Está Acontecendo?
No servidor: o horário renderizado pode ser:
10:00:01No cliente: milissegundos depois:
10:00:02Resultado: HTML diferente.
Hydration quebrada.
Erro Mais Comum em Next.js Moderno
Hoje o erro mais comum envolve:
App Router
Server Components
Client Components
Principalmente em aplicações híbridas.
Como Resolver Corretamente
Nesse caso:
'use client'
import { useEffect, useState } from 'react'
export default function Clock() {
const [time, setTime] = useState('')
useEffect(() => {
setTime(new Date().toLocaleTimeString())
}, [])
return <div>{time}</div>
}Agora: a renderização ocorre apenas no cliente.
Problema resolvido.
Outro Problema Muito Comum
Uso de:
window
localStorage
document
navigator
diretamente no SSR.
Exemplo Que Quebra
const width = window.innerWidthNo servidor: window não existe.
Forma Correta
'use client'
import { useEffect, useState } from 'react'
export default function Example() {
const [width, setWidth] = useState(0)
useEffect(() => {
setWidth(window.innerWidth)
}, [])
return <div>{width}</div>
}Diferença Entre Server e Client Components
Esse ponto virou MUITO importante no Next.js moderno.
Server Components
Executam:
no servidor
Podem:
acessar banco
acessar APIs
usar async/await diretamente
Não podem:
usar estado
usar useEffect
acessar window
Client Components
Executam:
no navegador
Podem:
usar hooks
interatividade
eventos
Precisam do:
'use client'Erro Muito Comum
Misturar lógica client dentro de server component.
Exemplo Problemático
export default function Page() {
const theme = localStorage.getItem('theme')
return <div>{theme}</div>
}Isso quebra hydration.
Solução Correta
Mover lógica para Client Component.
Outro Vilão: Math.random()
<div>{Math.random()}</div>Servidor: valor diferente.
Cliente: valor diferente.
Hydration quebra.
APIs Não Determinísticas
Cuidado com:
Date.now()
Math.random()
locale dinâmica
timezone
dados mutáveis
Tudo isso pode gerar HTML diferente.
Problemas de Biblioteca
Muitas bibliotecas antigas: não foram feitas para SSR.
Exemplos:
gráficos
animações
editores
mapas
Solução com Dynamic Import
import dynamic from 'next/dynamic'
const Chart = dynamic(
() => import('./Chart'),
{ ssr: false }
)Aqui: o componente renderiza apenas no cliente.
Quando Usar ssr: false?
Apenas quando necessário.
Muita gente usa isso como gambiarra.
E acaba destruindo:
SEO
performance
SSR
O Erro Não Está no React
Isso é importante.
O React está protegendo consistência.
Sem hydration correta:
eventos quebram
estados quebram
UI fica inconsistente
Como Identificar a Origem do Erro
A melhor forma é:
1.
Encontrar componente dinâmico
2.
Verificar:
Date
random
window
localStorage
3.
Verificar bibliotecas incompatíveis
4.
Comparar render server/client
Erro Muito Comum Com Tema Dark Mode
Exemplo clássico.
Tema muda no cliente:
HTML inicial é light
cliente troca para dark
Resultado: mismatch.
Solução Correta
Carregar tema após mount.
Exemplo
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) return nullMuito usado em:
next-themes
dark mode
preferências
suppressHydrationWarning Resolve?
Tecnicamente: sim.
Mas normalmente: é esconder problema.
Exemplo
<div suppressHydrationWarning>Use apenas: quando mismatch é esperado.
App Router Mudou Tudo
O Next.js moderno trouxe:
React Server Components
streaming
render híbrida
Isso melhorou:
performance
SEO
experiência
Mas aumentou MUITO:
complexidade
confusão
hydration issues
Como Evitar Problemas de Hydration
Separar Server e Client
Essa é a principal regra.
Evitar lógica dinâmica no SSR
Principalmente:
Date
random
browser APIs
Usar Client Component corretamente
Sem exagero.
Evitar gambiarra com ssr:false
Use conscientemente.
Testar produção
Muitos erros aparecem apenas:
em build
em deploy
em SSR real
Next.js Moderno Exige Nova Mentalidade
Esse é o ponto principal.
Antes: React era basicamente SPA.
Hoje: frontend virou híbrido.
Mistura:
backend
streaming
SSR
edge
cache
server rendering
E hydration virou parte fundamental disso.
Benchmark Real
Aplicações simples
Poucos problemas.
Dashboards complexos
Hydration aparece bastante.
SaaS grandes
Muito comum.
Aplicações com tema dinâmico
Erro extremamente frequente.
Bibliotecas visuais
Grande fonte de problemas.
Principais Causas do Hydration Failed
Problema | Frequência |
|---|---|
Date.now() | Alta |
Math.random() | Alta |
localStorage | Muito alta |
window/document | Muito alta |
Bibliotecas incompatíveis SSR | Alta |
Tema dark mode | Muito alta |
Dados dinâmicos inconsistentes | Alta |
Vale a Pena Usar Next.js Mesmo Assim?
Sim.
Muito.
Porque os benefícios:
SEO
performance
streaming
SSR
App Router
continuam enormes.
Mas o frontend moderno ficou mais complexo.
E hydration é parte disso.
Nossa Conclusão
O erro: Hydration Failed
não é apenas: “um bug aleatório”.
Na maioria das vezes ele revela:
mistura errada de server/client
renderização inconsistente
lógica dinâmica mal posicionada
Entender hydration corretamente virou praticamente obrigatório para quem trabalha com:
React moderno
Next.js
SSR
App Router
aplicações híbridas
Principalmente em projetos grandes.

