Next.js+MUI5通过Cookie切换明暗模式报className不匹配警告
问题根因
控制台抛出的Prop 'className' did not match是典型的SSR/SSG 水合不匹配错误,和当前Redux初始化主题状态的逻辑直接相关:
- 服务端预渲染页面时,运行环境是Node.js,无法读取浏览器端存储的Cookie,此时
Cookies.get('darkMode')返回undefined,Redux中darkMode初始值永远为false,最终服务端生成的所有DOM节点都是浅色模式对应的className。 - 页面下发到浏览器后,客户端JS加载运行,Redux初始化时成功读取到本地Cookie里的
darkMode=ON,状态变为true,首次客户端渲染生成的DOM全是深色模式对应的className。 - React做水合校验时,发现客户端生成的DOM className和服务端返回的初始DOM完全对不上,就会抛出上述警告,水合过程中断。导航栏作为布局层最先挂载的组件,可能在水合校验抛出错误前已经应用了深色样式,后续组件因为水合失败停止渲染,就出现了仅导航栏变深色、后续内容不加载的现象。
修复方案
核心原则是保证服务端和客户端首次渲染的状态、DOM结构完全一致,等水合完成后再同步客户端本地存储的主题状态:
- 调整Redux主题切片的初始值逻辑,移除初始化时直接读取Cookie的代码,统一将
darkMode初始值设为false,从根源上消除两端初始状态不一致的问题,同时新增一个显式设置主题状态的action:
import Cookies from 'js-cookie'; import { createSlice } from '@reduxjs/toolkit' const initialState = { darkMode: false, // 两端初始值统一,避免水合不匹配 } export const DarkModeSlice = createSlice({ name: 'darkMode', initialState, reducers: { // 新增显式设置主题的action,用于挂载后同步本地存储状态 setDarkMode: (state, action) => { state.darkMode = action.payload }, toggleDarkMode: (state) => { let newDarkMode = !state.darkMode; Cookies.set("darkMode", newDarkMode ? "ON" : "OFF"); state.darkMode = newDarkMode } }, }) export const { toggleDarkMode, setDarkMode } = DarkModeSlice.actions export default DarkModeSlice.reducer
- 在应用入口组件(Next.js对应
_app.js/tsx,纯React项目对应根App.js/tsx)中,通过useEffect在客户端挂载完成、水合结束后,再读取Cookie中存储的主题状态,同步到Redux中。useEffect只会在客户端执行,不会影响服务端渲染的初始结果:
import { useEffect } from 'react' import { useDispatch } from 'react-redux' import Cookies from 'js-cookie' import { setDarkMode } from '@/store/features/darkModeSlice' // 替换成实际的切片路径 export default function App({ Component, pageProps }) { const dispatch = useDispatch() useEffect(() => { // 水合完成后再同步本地存储的主题配置 const savedDarkMode = Cookies.get('darkMode') === 'ON' dispatch(setDarkMode(savedDarkMode)) }, [dispatch]) return <Component {...pageProps} /> }
- (可选优化)如果要修复首次进入页面时的主题闪烁问题,可以在项目入口HTML的
<head>标签内加入一段提前执行的内联脚本,在页面资源加载前就读取Cookie给根节点加上主题标识类,配合MUI的主题配置提前生效,这段脚本不影响React水合逻辑,因为它操作的是React挂载根节点之外的属性。
内容的提问来源于stack exchange,提问作者Ahmed Azzam
相关产品推荐
相关产品推荐

