next-themes icon indicating copy to clipboard operation
next-themes copied to clipboard

Warning: Extra attributes from the server: data-theme,style with App router

Open tomitrescak opened this issue 8 months ago • 4 comments

Hello,

I am unsure what am I doing wrong but themese work fine, but I'm getting the following warning in my console:

Warning: Extra attributes from the server: data-theme,style

I am using Next 14, app router. The Theme provider is added to my layout.tsx as following

This is the layout

"use server";

import { Providers } from "@/app/admin/providers";
import { getServerSession } from "next-auth";
import type { PropsWithChildren } from "react";

export default async function AdminLayout({
  children,
}: PropsWithChildren<{ view: string }>) {
  const session = getServerSession();
  return (
    <Providers session={session}>
      <div className="flex h-full overflow-hidden">
        My Content
      </div>
    </Providers>
  );
}

This is the provider

"use client";
import { SessionProvider } from "next-auth/react";
import { ThemeProvider } from "next-themes";

export function Providers({
  children,
  session,
}: {
  children: React.ReactNode;
  session: Any;
}) {
  return (
    <SessionProvider session={session}>
      <ThemeProvider forcedTheme="dark">{children}</ThemeProvider>
    </SessionProvider>
  );
}

tomitrescak avatar Nov 06 '23 07:11 tomitrescak

Hey! I've come to the same problem as you and found useful discussions about it on issue #180 and this discussion.

julianastahelin avatar Nov 07 '23 11:11 julianastahelin

I faced the same kind of problem today. To add a little more precision to what @julianastahelin said, here is the Error explanation of NextJS: https://nextjs.org/docs/messages/react-hydration-error

On my side I choose to use the: "isClient" technic which will: "Ensure that the component renders the same content server-side as it does during the initial client-side render to prevent a hydration mismatch."

And it solve my problem 👍

PS: on my side (still don't understand why) I need to do this when I declare the ThemeProvider, like this:

"use client";

import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
import { useEffect, useState } from "react";

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  // Ensure that the component renders the same content server-side as it does during the initial client-side render to prevent a hydration mismatch.
  const [isClient, setIsClient] = useState(false);

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

  return (
    isClient && <NextThemesProvider {...props}>{children}</NextThemesProvider>
  );
}

MartinGbz avatar Nov 24 '23 15:11 MartinGbz

I faced the same kind of problem today. To add a little more precision to what @julianastahelin said, here is the Error explanation of NextJS: https://nextjs.org/docs/messages/react-hydration-error

On my side I choose to use the: "isClient" technic which will: "Ensure that the component renders the same content server-side as it does during the initial client-side render to prevent a hydration mismatch."

And it solve my problem 👍

PS: on my side (still don't understand why) I need to do this when I declare the ThemeProvider, like this:

"use client";

import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
import { useEffect, useState } from "react";

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  // Ensure that the component renders the same content server-side as it does during the initial client-side render to prevent a hydration mismatch.
  const [isClient, setIsClient] = useState(false);

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

  return (
    isClient && <NextThemesProvider {...props}>{children}</NextThemesProvider>
  );
}

This will result in the Server Component below the ThemeProvider not being rendered during the pre-rendering process.

You can open the Network tab in your browser's DevTools to check the document received when the page initially loads.

martinuc avatar Feb 06 '24 07:02 martinuc

Yep you are right, I use now this system only in composants/page where I have the hydration issue. But tbh, I always have the impression the hydration error appear randomly (sometimes I have it, sometimes no on certain components)

MartinGbz avatar Feb 06 '24 17:02 MartinGbz