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>;
}
Within your layout.tsx
, remove <html>
and <body>
tags.
If you have a need for <head>
tag, use the component <Head>
from Next.js like:
import Head from 'next/head'
So your layout.tsx
becomes:
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 (
<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 />
{children}
</div>
</main>
</ThemeProvider>
);
}
You also need to verify that within Sidebar
and Navbar
components, you have only valid html according to W3C (failing which you shall hydration error from Next.js).