Ed Brissenden
Ed Brissenden

Reputation: 309

Can Next.JS className be set programatically with useContext? Getting error "Warning: Prop `className` did not match."

I have a child component which needs to dynamically render a className based on the value of useContext. When I do this, Next.JS gives the following error:

Warning: Prop className did not match. Server: "some-class some-other-class " Client: "some-class some-other-class dark-theme"

I think I understand why there is a mismatch: the value of the context is true on the client (when modified by a user interacting with a parent component) but false on the server. But how do I overcome this issue? I have seen similar errors reported but not due to a dynamic class name. Thank you in advance.

Example code:

'use client';

import { useContext } from "react";
import { CustomThemeContext, CustomThemeProviderContext } from "@/contexts/custom-theme";
import Link from "next/link";
import './styles.scss';

export default function SomeComponent() {

  const { useDarkTheme, setUseDarkTheme } = useContext<CustomThemeProviderContext>(CustomThemeContext);

  const themeClassName = useDarkTheme ? 'dark-theme' : '';

  return (
      <h1 className={`some-class some-other-class ${themeClassName}`}>
        Welcome
      </h1>
  );
}
export interface CustomThemeProviderContext {
  useDarkTheme: boolean;
  setUseDarkTheme: (useDarkTheme: boolean) => void;
}
export const CustomThemeContext: any = createContext<CustomThemeProviderContext>({
  useDarkTheme: false,
  setUseDarkTheme: (useDarkTheme: boolean): void => {
  }
});

Upvotes: 0

Views: 37

Answers (1)

Ahmed Abdelbaset
Ahmed Abdelbaset

Reputation: 4946

You are correct in your understanding. React Context is unavailable during Server Rendering, and React will revert to the default context value (useDarkTheme false) until hydration occurs. To prevent the mismatch error, you can set the suppressHydrationWarning property on the element that differs between Server and Client rendering.

  return (
      <h1 suppressHydrationWarning className={`some-class some-other-class ${themeClassName}`}>
        Welcome
      </h1>
  );

This property will suppress the hydration error, however, the layout shift problem persists.

To address the layout shift issue, the value must be stored in a location accessible by both the Client and the Server for example, user session or cookies.

Upvotes: 0

Related Questions