Next.js+MUI主题切换持久化失效及className不匹配问题求助
Next.js + MUI主题切换问题排查请求
我在Next.js Web应用中使用MUI实现了系统、深色、浅色三种主题切换功能,通过localStorage保存用户选中的主题以实现会话间持久化,在设置模态框的下拉菜单中通过useContext完成主题切换操作。目前遇到两个核心问题:
- 当用户选择系统主题(系统本身为深色模式时)或深色主题时,主题无法在所有组件中保持一致;
- 初始加载非浅色主题,或者从浅色主题切换到其他主题时,会出现如下错误:
Warning: Prop className did not match. Server: "MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-edgeStart MuiIconButton-sizeMedium css-134qg7o-MuiButtonBase-root-MuiIconButton-root" Client: "MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-edgeStart MuiIconButton-sizeMedium css-6pxnsq-MuiButtonBase-root-MuiIconButton-root"
最初我以为是未在ThemeProvider标签内使用CssBaseline导致的问题,但添加后问题反而加重,错误依然存在。
不同场景表现截图
- 系统或深色模式下的预期表现(未添加CssBaseline):

- 未添加CssBaseline时,系统或深色模式加载后的实际表现:

- 添加CssBaseline后,系统或深色模式加载后的表现:

- 从浅色主题切换到系统或深色主题时的表现:

主题上下文代码
const ThemeContext = createContext() const useThemeContext = () => useContext(ThemeContext) export const ThemeModeProviderComponent = ({ children }) => { const systemTheme = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' const [selectedTheme, setSelectedTheme] = useState(() => typeof localStorage !== 'undefined' && localStorage.getItem('theme') || 'system' ) const themes = { light: createTheme({ palette: { mode: 'light', primary: { main: '#0065bd' }, secondary: { main: '#00b6d3' } } }), dark: createTheme({ palette: { mode: 'dark', primary: { main: '#0065bd' }, secondary: { main: '#00b6d3' } } }), system: createTheme({ palette: { mode: systemTheme, primary: { main: '#0065bd' }, secondary: { main: '#00b6d3' } } }) } useEffect(() => { if (selectedTheme === 'system') { const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' themes.system.palette.mode = systemTheme } }, [selectedTheme, themes.system]) const handleThemeChange = (event) => { const { value } = event.target setSelectedTheme(value) localStorage.setItem('theme', value) } return ( <ThemeContext.Provider value={{ selectedTheme, handleThemeChange }}> <ThemeProvider theme={themes[selectedTheme]}> <CssBaseline enableColorScheme/> {children} </ThemeProvider> </ThemeContext.Provider> ) } export const ThemeSelector = () => { const { selectedTheme, handleThemeChange } = useThemeContext() if (typeof window === 'undefined') return null return ( <FormControl> <Select value={selectedTheme} onChange={handleThemeChange} > <MenuItem value='system'>System</MenuItem> <MenuItem value='dark'>Dark</MenuItem> <MenuItem value='light'>Light</MenuItem> </Select> </FormControl> ) }
其他可能影响因素
抽屉组件的显示/隐藏逻辑可能影响样式,我基本照搬了MUI官网的持久化抽屉示例,但从截图看该组件能正常工作,暂时不确定是否与此相关。请帮忙排查并解决这些问题。
内容的提问来源于stack exchange,提问作者Lofton Gentry
相关产品推荐
相关产品推荐

