Hydration errors in development for Next.js app with MUI Material v5 after updating emotion dependencies
ddembo opened this issue · 20 comments
Current behavior:
We are getting hydration errors in development on pages that render components which are styled MUI components, after updating the following dependencies:
@emotion/cache
from11.11.0
to11.13.0
@emotion/react
from11.11.4
to11.13.0
@emotion/styled
from11.11.5
to11.13.0
Warning: Prop `className` did not match. Server: "MuiTableCell-root MuiTableCell-body MuiTableCell-sizeSmall e18whkzw0 mui-az1ynu-MuiTableCell-root-TableCellLinkContainer" Client: "MuiTableCell-root MuiTableCell-body MuiTableCell-sizeSmall e18whkzw0 mui-1odz46y-MuiTableCell-root-TableCellLinkContainer"
Notably, we did not update MUI or any related dependencies at the same time.
It only affects components created using the styled
helper, e.g.:
import styled from "@emotion/styled";
import TableRow from "@mui/material/TableRow";
const StyledTableRow = styled(TableRow)({
"&:last-child > th, &:last-child > td": {
borderBottom: 0,
},
});
export default StyledTableRow;
It seems to be a problem with one of those packages' underlying dependencies, because the issue disappears when we use the old package-lock.json
, but not if we nuke and recreate it.
I've been trying to identify the root cause but I'm finding it difficult, I'm not very familiar with the internals of emotion. I think it could be a problem with the serialiser, because the client <style>
tags being inserted look to me like the data-emotion
attributes are missing the serialized classnames that typically seem to follow the cache prefix mui
, e.g.:
It could also be a problem with the hash
package, since the hashed part of the className is different.
The issue is not present in production builds of the app.
To reproduce:
CSB: TODO later if I have some more time
- Make a styled MUI component as described above, put it on a Next.js page.
- Visit that route in a browser, open devtools.
Expected behavior:
Classnames should match on both client & server, no hydration errors.
Environment information:
"react": "^18.3.1",
"@emotion/react": "^11.13.0",
"@emotion/cache": "^11.13.0",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.13.0",
"@mui/material": "^5.16.4",
"@mui/material-nextjs": "^5.16.4",
same here, we need it to be fixed.
I need a runnable repro case to investigate this.
I can get that over to you tomorrow.
I'd appreciate that, thanks!
interestingly, when I shrink the project to bare minimum, the issue is gone, I will need to do more research.
FWIW, I am getting this problem with:
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
I think this is introduced as an issue with this change. The server now defaults to using emotion-serialize.cjs.js
while webpack will automatically use development.cjs.js
version. The non-development version excludes sourceMaps explicitly from the serialization algorithm while the development version does not.
It doesn't seem reasonable to assume that users will know to add --conditions
to the node process to fix this development issue, especially when it is still an experimental flag.
Setting an override in my package.json
fixed this for me:
"overrides": {
"@emotion/serialize": "1.2.0"
}
@mridgway I can confirm I have this issue even with 1.2.0
▶ cat pnpm-lock.yaml | grep @emotion/serialize
'@emotion/serialize':
'@emotion/serialize@1.2.0':
'@emotion/serialize': 1.2.0
'@emotion/serialize': 1.2.0
'@emotion/serialize@1.2.0':
'@emotion/serialize': 1.2.0
'@emotion/serialize': 1.2.0
It doesn't seem reasonable to assume that users will know to add --conditions to the node process to fix this development issue, especially when it is still an experimental flag.
This is news to me. I totally considered this a stable feature. It's mentioned multiple times in other parts of the docs and is never guarded with the experimental warning at those places. On top of that, node.js doesn't emit any experimental features warnings when you use custom conditions so it's not apparent at all that it's experimental.
That said, I don't know how we are supposed to deal with this. The environment needs to be in a cohesive state. What kind of setup are you using? Is your server created manually?
I think this is introduced as an issue with this change. The server now defaults to using
emotion-serialize.cjs.js
while webpack will automatically usedevelopment.cjs.js
version. The non-development version excludes sourceMaps explicitly from the serialization algorithm while the development version does not.It doesn't seem reasonable to assume that users will know to add
--conditions
to the node process to fix this development issue, especially when it is still an experimental flag.Setting an override in my
package.json
fixed this for me:"overrides": { "@emotion/serialize": "1.2.0" }
I can confirm that the override works for me, after override it back to 1.2.0, and redo npm install, the warning is gone.
I think this is a red herring. My current version of code uses @emotion/serialize@1.1.4
in my pnpm-lock.yaml file.
The only emotion packages I use/specify in my package.json files are:
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
I think this is introduced as an issue with this change. The server now defaults to using
emotion-serialize.cjs.js
while webpack will automatically usedevelopment.cjs.js
version. The non-development version excludes sourceMaps explicitly from the serialization algorithm while the development version does not.It doesn't seem reasonable to assume that users will know to add
--conditions
to the node process to fix this development issue, especially when it is still an experimental flag.Setting an override in my
package.json
fixed this for me:"overrides": { "@emotion/serialize": "1.2.0" }
Using MUI Material v5 with Nextjs Pages router and got this exact problem after updating emotion dependencies.
While I don't have "@emotion/serialize"
directly in my package.json
overriding "@emotion/serialize"
as mentioned, running install and restarting the server fixed it for me
Once I get the repro case of the problem, I could investigate this
As an additional data point, I've been seeing these errors since MUI 5.16.0
and have been pinned on 5.15.21
until I had time to put together a reproduction. I got the emotion changes today and am using @emotion/serialize: 1.3.0
. So it's possible that there are several overlapping issues here causing the same failures, as suggested by @jakeleventhal.
Is there a way to actually fix it without overriding dependencies and downgrading packages?