我有一个子组件,需要根据 useContext 的值动态渲染 className。当我这样做时,Next.JS 给出以下错误:
警告:道具
className
不匹配。服务器:“some-class some-other-class” 客户端:“some-class some-other-class 黑暗主题”
我想我明白为什么会出现不匹配:上下文的值在客户端上为 true(当用户与父组件交互时进行修改时),但在服务器上为 false。但我该如何克服这个问题呢?我见过类似的错误报告,但不是由于动态类名造成的。预先感谢您。
示例代码:
'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 => {
}
});
您的理解是正确的。 React Context 在服务器渲染期间不可用,React 将恢复为默认上下文值 (
useDarkTheme false
),直到发生水合作用。为了防止不匹配错误,您可以在服务器和客户端渲染之间不同的元素上设置 suppressHydrationWarning
属性。
return (
<h1 suppressHydrationWarning className={`some-class some-other-class ${themeClassName}`}>
Welcome
</h1>
);
此属性将抑制水合误差,但是,布局偏移问题仍然存在。
为了解决布局偏移问题,该值必须存储在客户端和服务器都可以访问的位置,例如用户会话或 cookie。