NextJS搭配MUI出现Hydration失败问题求助
解决MUI组件在Next.js中Hydration不匹配的问题
问题原因
报错源于MUI基于Emotion的样式在服务端渲染(SSR)和客户端渲染时生成的HTML结构不一致,具体表现为Box组件的style标签在两端输出不匹配,触发Next.js的Hydration校验失败。
解决步骤
1. 正确配置Emotion的SSR支持(核心方案)
在Next.js App Router中,需手动配置Emotion确保服务端与客户端样式同步:
- 创建
src/lib/emotion.tsx文件,内容如下:'use client'; import createCache from '@emotion/cache'; import { useServerInsertedHTML } from 'next/navigation'; import { CacheProvider as EmotionCacheProvider } from '@emotion/react'; import React from 'react'; export default function CacheProvider({ children }: { children: React.ReactNode }) { const [cache] = React.useState(() => { const cache = createCache({ key: 'mui' }); cache.compat = true; return cache; }); useServerInsertedHTML(() => { return ( <style data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`} dangerouslySetInnerHTML={{ __html: Object.values(cache.inserted).join('') }} /> ); }); return <EmotionCacheProvider value={cache}>{children}</EmotionCacheProvider>; } - 在根
app/layout.tsx中导入并使用该CacheProvider,包裹整个应用:import CacheProvider from '@/lib/emotion'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="zh-CN"> <body> <CacheProvider>{children}</CacheProvider> </body> </html> ); }
2. 替换Box组件为原生元素(临时排查/替代方案)
若配置Emotion后问题仍存在,可尝试将Header中的Box替换为原生div,规避MUI组件的样式生成差异:
// 替换前 <Box sx={{ flexGrow: 1 }}> // 替换后 <div style={{ flexGrow: 1 }}>
若替换后错误消失,说明问题确实出在MUI组件的SSR样式生成逻辑上,需确保Emotion配置完全正确。
3. 检查版本兼容性
确保@mui/material(v5+)与next(13+)版本兼容,版本不匹配可能导致SSR样式生成异常。可运行以下命令更新至兼容版本:
npm install next@latest @mui/material@latest @emotion/react@latest @emotion/styled@latest
4. 避免使用客户端依赖的动态样式
确保所有sx属性值为静态内容,不要依赖window、document等仅客户端存在的对象,这类动态值会导致服务端与客户端渲染结果不一致。
内容的提问来源于stack exchange,提问作者Kman
相关产品推荐
相关产品推荐

