[Fixed] Using next-themes for dark mode generates hydration failed error – Next.js

by
Ali Hasan
darkmode next.js tailwind-css

Quick Fix: In your layout.tsx, remove unnecessary tags like <html> and <body>. Utilize Next.js components like <Head> for the <head> tag if required. Ensure HTML within Sidebar and Navbar components is valid according to W3C standards.

The Problem:

In a React application, after implementing a dark mode feature using the next-themes library, the page encounters a ‘Hydration failed’ error during client-side rendering. The error message indicates that the initial UI on the client does not match the server-rendered HTML. Additionally, a warning message suggests that a matching <script> tag inside the <html> element is expected on the server-side.

The Solutions:

Solution 1: Omit <html> and <body> tags in layout.tsx

  1. Remove the &lt;html&gt; and &lt;body&gt; tags from your layout.tsx file.

  2. If you need the &lt;head&gt; tag, import the &lt;Head&gt; component from Next.js like import Head from &#39;next/head&#39;.

  3. Modify your layout.tsx file as follows:

import Navbar from "@/components/Navbar";
import "./globals.css";
import type from "next";
import from "next/font/google";
import Sidebar from "@/components/Sidebar";
import 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 (
<ThemeProvider>
<main className={${nunito_sans.className} bg-gradient-to-r from-green to to-blue-400 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 />
</div>
</main>
</ThemeProvider>
);
}


4. Ensure that the `Sidebar` and `Navbar` components contain valid HTML according to W3C standards.

Solution 2: Using suppressHydrationWarning

To resolve this issue, add the suppressHydrationWarning prop to the html element within your layout.tsx file:

export default function RootLayout({ children }: { children: React.ReactNode }) 
{
  return (
    &lt;html lang=&quot;en&quot; suppressHydrationWarning&gt;
      &lt;body&gt;
          &lt;ThemeProviders&gt;
            {children}
          &lt;/ThemeProviders&gt;
          
        &lt;/body&gt;
    &lt;/html&gt;
  );
}

By adding this prop, you instruct Next.js to suppress the hydration warning for the mismatched initial UI caused by the dynamic background color change. This allows the page to render correctly without affecting the functionality of your dark mode.

Q&A

Why I get the hydration failed error?

You have &lt;html&gt; and &lt;body&gt; within your layout.tsx component which is causing it to fail hydration.

What change do I need to make to stop the hydration failed error?

To stop the hydration error, you need to remove the &lt;html&gt; and &lt;body&gt; tags from your layout.tsx.

Video Explanation:

The following video, titled "Dark Mode in Next JS 13 App Directory with TailwindCSS (for ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

Learn how to add dark mode to your Next.js 13 application that uses app directory. Using different themes with Next JS 13 application can ...