3 minutos de lectura
0
Los errores de hydration (o hydration mismatch) aparecen cuando el HTML renderizado en el servidor no coincide con lo que React pinta en el cliente.
Con next-themes y App Router (Next 13/14) esto sucede porque el componente <ThemeProvider />
lee window.matchMedia
, localStorage
, etc. —APIs que no existen durante el SSR—.
El resultado típico es:
A continuación veremos:
ThemeProvider
sin SSR.layout.tsx
.useTheme()
desde cualquier Client Component con un ejemplo de ThemeSwitcher
.layout.tsx
se ejecuta primero en el servidor.window
y almacenamiento local no existen allí → el HTML sale con un tema “por defecto”.La solución es renderizar ThemeProvider
solo en el navegador.
ThemeProvider
compatible con App Routersrc/providers/theme-provider.tsx
src/app/layout.tsx
Ahora tu árbol React en el servidor no incluye ThemeProvider
, evitando el desajuste.
Con el provider configurado, puedes usar useTheme()
en cualquier Client Component para leer o cambiar el tema.
src/components/theme-switcher.tsx
Coloca <ThemeSwitcher />
en tu navbar o en cualquier parte del cliente y funcionará sin parpadeos ni warnings.
Buenas prácticas | Explicación |
---|---|
suppressHydrationWarning en <html> | Evita warnings de React cuando cambie la clase de tema |
disableTransitionOnChange | Quita flickering si usas Tailwind o CSS con transiciones |
Persistir preferencia | El propio next-themes guarda el tema en localStorage ; si prefieres cookies, lee useTheme() y persiste manualmente |
Tailwind | Asegúrate de darkMode: "class" en tailwind.config.js |
ThemeProvider
dinámicamente con ssr:false
y envolver tu aplicación.useTheme()
funciona en cualquier Client Component (ej. ThemeSwitcher
).¡Listo! Ahora tu Next.js App Router soporta dark/light mode sin errores de hidratación. ¿Preguntas o sugerencias? ¡Déjalas en los comentarios!
Si lo deseas, puedes apoyarme con una donación voluntaria. Tu aporte me permite dedicar más tiempo a investigar, escribir y mejorar la calidad del contenido que publico. ¡Muchísimas gracias por considerar impulsar este proyecto!
Compartir en: