You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的实际表现
  • 添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 20:42:19