Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using next-themes for dark mode generates hydration failed error

I am trying to implement a dark mode using next-themes. Inside the layout.tsx file, <body> contains a background color. Hence, I need to wrap the whole <body> inside <ThemeProvider> to change the background as well when toggling to dark mode. I am importing the <ThemeProvider> from ./lib/providers.ts as a client component to avoid making the whole app a client component.

providers.ts file as follows:

"use client";

export { ThemeProvider } from "next-themes";

while the layout.tsx file is as follows:

import Navbar from "@/components/Navbar";
import "./globals.css";
import type { Metadata } from "next";
import { Nunito_Sans } from "next/font/google";
import Sidebar from "@/components/Sidebar";
import { ThemeProvider } from "@/lib/providers";

const nunito_sans = Nunito_Sans({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "My name | Portfolio",
  description: "My moto",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <ThemeProvider>
        <body
          className={`${nunito_sans.className} bg-gradient-to-r from-green to to-blue-400`}
        >
          <main className="grid grid-cols-12 gap-6 my-14 px-5 lg:px-48 sm:px-20 md:px-32">
            <div className="col-span-12 lg:col-span-3 bg-white rounded-2xl p-4 text-center">
              <Sidebar />
            </div>
            <div className="col-span-12 lg:col-span-9 bg-white rounded-2xl flex flex-col overflow-hidden">
              <Navbar />
              {children}
            </div>
          </main>
        </body>
      </ThemeProvider>
    </html>
  );
}

However, it throughs an error:

❌ Error
Hydration failed because the initial UI does not match what was rendered on the server.
⚠️ Warning
Expected server HTML to contain a matching in .

I have also tried creating a separate component <Provider> and wrapping the body inside it but, the same warning occurs:

"use client";

import { ThemeProvider } from "next-themes";

export default function Providers({ children }: { children: React.ReactNode }) {
  return <ThemeProvider>{children}</ThemeProvider>;
}
like image 708
Fahad Avatar asked Dec 01 '25 23:12

Fahad


2 Answers

Add suppressHydrationWarning this is what the official documentation says;

Note! If you do not add suppressHydrationWarning to your <html> you will get warnings because next-themes updates that element. This property only applies one level deep, so it won't block hydration warnings on other elements.

https://github.com/pacocoursey/next-themes

like image 54
Johan Avatar answered Dec 03 '25 13:12

Johan


First Step:

To resolve this, you can conditionally render the ThemeProvider only after the component has mounted on the client side. This approach ensures that the server-side rendering does not conflict with client-side rendering.

"use client";

import { ThemeProvider } from "next-themes";
import { useState, useEffect } from "react";

export default function Providers({ children }: { children: React.ReactNode }) {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return <>{children}</>; // Render children without ThemeProvider during SSR
  }

  return <ThemeProvider attribute="class">{children}</ThemeProvider>; // Wrap children with ThemeProvider after mount
}

Second Step: Update Your Layout Component: Use the Providers component to wrap your main content in layout.tsx.

import type { Metadata } from "next";
import Providers from "./providers";
import "./globals.css";

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {

  return (
    <html lang="en">
      <body>
        <Providers>
        {children}
        </Providers>
      </body>
    </html>
  );
}

Now you are all set wont see any hydration warning

like image 35
Ansh Avatar answered Dec 03 '25 12:12

Ansh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!