material-ui
material-ui copied to clipboard
Hydration error in next.js with MUI
Steps to reproduce
I am using a <LoadingButton /> in my app. I can't reliably reproduce this. In most cases, it works fine. Sometimes it doesn't.
Current behavior
Button uses default MUI styling and ignores all the theme overrides I have upon a hard refresh. When navigating to the page via next.js routing, it works fine. Then if I refresh, the styles use the default MUI stylings. In the console I get the following warning:
[Error] Warning: Prop `className` did not match. Server: "MuiButtonBase-root MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-fullWidth MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-fullWidth css-sppx0e-MuiButtonBase-root-MuiButton-root-MuiLoadingButton-root" Client: "MuiButtonBase-root MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-disableElevation MuiButton-fullWidth MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-disableElevation MuiButton-fullWidth css-e1igr2-MuiButtonBase-root-MuiButton-root-MuiLoadingButton-root"
button
MuiButtonBase-root
ButtonBase
MuiButton-root
Button
MuiLoadingButton-root
LoadingButton
div
Styled(div)
Box
form
div
Styled(div)
Box
section
MuiContainer-root
Container
div
Styled(div)
Box
ContentWrapper
ContactFormSection
ContactUs
Contact
div
Styled(div)
Box
div
Styled(div)
Box
HeaderStateContext
DefaultLayout
ConfirmationDialogProvider
Component@
QueryClientProvider
ReactQueryWrapper
Component@
SnackbarProvider
RtlProvider
ThemeProvider
ThemeProvider
ThemeProvider
ThemeProvider
SettingsProvider
div
MotionComponent
LazyMotion
MotionLazy
App
AppLayout
Provider
Integrow
PathnameContextProviderAdapter
PureComponent@
ReactDevOverlay
Component@
AppContainer
Root
"
See more info here: https://nextjs.org/docs/messages/react-hydration-error"
(anonymous function) (hydration-error-info.js:63)
(anonymous function) (setup-hydration-warning.js:18)
printWarning (react-dom.development.js:86)
error (react-dom.development.js:60)
warnForPropDifference (react-dom.development.js:9571)
diffHydratedProperties (react-dom.development.js:10414)
prepareToHydrateHostInstance (react-dom.development.js:12564)
completeWork (react-dom.development.js:22176)
completeUnitOfWork (react-dom.development.js:26591)
performUnitOfWork (react-dom.development.js:26563)
workLoopSync (react-dom.development.js:26461)
renderRootSync (react-dom.development.js:26429)
performConcurrentWorkOnRoot (react-dom.development.js:25733:89)
workLoop (scheduler.development.js:266)
flushWork (scheduler.development.js:239)
performWorkUntilDeadline (scheduler.development.js:533)
In the screenshot you can see the difference. The fonts/styles are using the default MUI styles:
Expected behavior
Button loads with correct styles always
Context
No response
Your environment
System:
OS: macOS 15.0
Binaries:
Node: 20.14.0 - ~/.nvm/versions/node/v20.14.0/bin/node
npm: 10.7.0 - ~/.nvm/versions/node/v20.14.0/bin/npm
pnpm: 9.5.0 - ~/.nvm/versions/node/v20.14.0/bin/pnpm
Browsers:
Chrome: 126.0.6478.183
Edge: Not Found
Safari: 18.0
npmPackages:
@mui/lab: 5.0.0-alpha.171 => 5.0.0-alpha.171
@mui/material: 5.16.4 => 5.16.4
@mui/material-nextjs: 5.16.4 => 5.16.4
@types/react: 18.3.3 => 18.3.3
react: 18.3.1 => 18.3.1
react-dom: 18.3.1 => 18.3.1
Tried in safari and chrome
Search keywords: loadingbutton hydration
We are also experiencing this issue, after updating emotion dependencies, we are getting hydration errors in styled MUI components. I raised an issue. @emotion/styled and other packages are a peer dependency of multiple MUI packages.
Amen plz we have this issue too
same here!
Same problem here with Nextjs Pages router. For anyone looking for a fix, I recommend trying to override "@emotion/serialize" as mentioned in the linked issue by @ddembo
I am using Next.js v15.1.0 with the App Router and encountered a hydration error.
The issue was resolved by wrapping the MUI AppBar component with a Box component, which fixed the error.
I’m sharing this here in case it might help someone facing a similar problem.
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
<Box>
<AppBar position="static" sx={{ backgroundColor: "#0d0402" }}>
<Container
sx={{
maxWidth: "1200px",
textAlign: "center",
}}
>
<Toolbar disableGutters sx={{ justifyContent: "space-between" }}>
...
</Toolbar>
</Container>
</AppBar>
</Box>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
I don't know if my issue is similar, but I'm facing another hydration error.
Error text:
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:
- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.
It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
https://react.dev/link/hydration-mismatch
Package.json
"@emotion/cache": "11.14.0",
"@emotion/react": "11.14.0",
"@emotion/server": "11.11.0",
"@emotion/styled": "11.14.0",
"@mui/material": "6.2.0",
"@mui/material-nextjs": "^6.2.0",
"@mui/system": "6.2.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"next": "15.1.0"
I'm using pages router, and the functions/components from @mui/material-nextjs/v15-pagesRouter are set up correctly in code. I also tried opening in icognito but it's the same.
I've some issues too. Maybe it is related. I built a small minimal example, but I can't see the reason why http://localhost:3000 cause a hydration error: https://github.com/Tockra/nextjs-test-playground/tree/mui-cache-problem
I built my loading page in my main application similar. This causes a lot of hydration problems in nextjs dev mode.
I am using Next.js v15.1.0 with the App Router and encountered a hydration error.
The issue was resolved by wrapping the MUI
AppBarcomponent with aBoxcomponent, which fixed the error.I’m sharing this here in case it might help someone facing a similar problem.
<html lang="en"> <body className={`${geistSans.variable} ${geistMono.variable}`}> <Box> <AppBar position="static" sx={{ backgroundColor: "#0d0402" }}> <Container sx={{ maxWidth: "1200px", textAlign: "center", }} > <Toolbar disableGutters sx={{ justifyContent: "space-between" }}> ... </Toolbar> </Container> </AppBar> </Box> <ThemeProvider>{children}</ThemeProvider> </body> </html>
this one is caused by the chrome extension Colorzilla other way to fix it would be just disabling the extension i guess
My fix is here and would likely close this Issue.
The unreliability in reproduction noted in the OP might be due to the full vs. fast refresh issue noted in that linked comment.
I get sick of this error popping up all the time. Almost dread working with next and new libraries. I just use the old useeffect trick, got sick of trying to fix these errors all the time, takes up too much time. Vercel need to have a hard look at how they can sort this out. Ever since they have had SSR, they have had this issue. Everyone has to jump through hoops to get it working. I know its not directly their fault, but they should have had a fix by now, not just hacks, a fix.