¿Qué es el Error 'Hydration Failed' en Next.js?
El error Hydration Failed o Text content does not match server-rendered HTML es uno de los problemas más comunes al desarrollar aplicaciones web utilizando Server-Side Rendering (SSR) con Next.js y React. Ocurre cuando el HTML generado por el servidor no coincide con el primer renderizado generado en el cliente (navegador) durante el proceso de hidratación.
Causas Principales del Error de Hidratación
Este fallo de discrepancia suele estar provocado por diversos factores relacionados con la manipulación del DOM y el estado inicial de la aplicación:
- Uso de funciones que devuelven valores dinámicos en el cliente como
new Date(),Math.random()o variables basadas enlocalStorage. - Extensiones del navegador que modifican el HTML inyectando atributos antes de que React complete la hidratación.
- Estructuras HTML inválidas (por ejemplo, anidar etiquetas
<p>dentro de otras o etiquetas<div>dentro de<p>).
Método 1: Sincronizar el renderizado con useEffect
La forma más limpia de evitar diferencias entre el servidor y el cliente es retrasar la renderización de componentes dinámicos hasta que el componente se haya montado en el navegador.
- Identifica el componente que utiliza datos dinámicos (como la fecha u hora actual).
- Crea una variable de estado booleana llamada
isMountedinicializada enfalse. - Utiliza el hook
useEffectpara cambiar su valor atrueuna vez montado el componente.
import { useState, useEffect } from 'react';
export default function DynamicComponent() {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
if (!isMounted) {
return null; // O un marcador de posición (skeleton loader)
}
return <div>{new Date().toLocaleTimeString()}</div>;
}Método 2: Usar el atributo suppressHydrationWarning
Si estás seguro de que la discrepancia es inofensiva (por ejemplo, atributos inyectados por extensiones del navegador o marcas de tiempo irrelevantes), puedes indicarle a React que ignore la advertencia en un elemento específico.
- Localiza la etiqueta JSX donde se produce la divergencia en el DOM.
- Añade el atributo booleano
suppressHydrationWarning={true}directamente en la etiqueta afectada.
<div suppressHydrationWarning={true}>
{new Date().toLocaleDateString()}
</div>Nota: Utiliza este método solo como último recurso, ya que no soluciona el problema de raíz, sino que silencia la advertencia de React en la consola.
Método 3: Desactivar el SSR en componentes específicos
Si un componente depende exclusivamente de APIs del navegador como window o document y no puede ser renderizado en el servidor, puedes importarlo dinámicamente desactivando el Server-Side Rendering.
- Abre el archivo donde vas a consumir el componente problemático.
- Utiliza
next/dynamiccon la opciónssr: false.
import dynamic from 'next/dynamic';
const ClientOnlyComponent = dynamic(
() => import('../components/ClientOnly'),
{ ssr: false }
);
export default function Page() {
return (
<main>
<ClientOnlyComponent />
</main>
);
}