material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

Hydration error in next.js with MUI

Open jakeleventhal opened this issue 1 year ago • 2 comments

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: Screenshot 2024-07-23 at 4 42 36 PM Screenshot 2024-07-23 at 4 42 47 PM

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

jakeleventhal avatar Jul 23 '24 20:07 jakeleventhal

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.

ddembo avatar Jul 24 '24 00:07 ddembo

Amen plz we have this issue too

robneir avatar Jul 24 '24 00:07 robneir

same here!

OliverwengFiltered avatar Jul 25 '24 17:07 OliverwengFiltered

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

PeanutButte7 avatar Jul 30 '24 18:07 PeanutButte7

I am using Next.js v15.1.0 with the App Router and encountered a hydration error. image

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>

mani444 avatar Dec 18 '24 13:12 mani444

image

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.

HasanMothaffar avatar Dec 19 '24 06:12 HasanMothaffar

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

Image

I built my loading page in my main application similar. This causes a lot of hydration problems in nextjs dev mode.

Tockra avatar Feb 21 '25 13:02 Tockra

I am using Next.js v15.1.0 with the App Router and encountered a hydration error. image

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>

this one is caused by the chrome extension Colorzilla other way to fix it would be just disabling the extension i guess

tuxo avatar Feb 24 '25 11:02 tuxo

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.

boiseiben avatar Mar 11 '25 14:03 boiseiben

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.

maxpowernz avatar Apr 07 '25 05:04 maxpowernz