material-ui
material-ui copied to clipboard
Next.js + Material UI v5 styled-component example is still showing className mismatch error
- [ x] The issue is present in the latest release.
- [ x] I have searched the issues of this repository and believe that this is not a duplicate.
Current Behavior 😯
I've followed the example for nextjs styled-components.
The example works out of the box.
However, once you create a styled-component, the className did not match from server side rendering error will occur.
https://github.com/mui-org/material-ui/tree/75f27074b89381d25a1fab85fc2098af58e89cb0/examples/nextjs-with-styled-components-typescript
Prop
className
did not match. Server: "sc-dlnjwi fBCjsW MuiBox-root" Client: "sc-gtsrHT kMdZqK MuiBox-root"
Expected Behavior 🤔
The example should work like it should.
Steps to Reproduce 🕹
I've forked the example ( from above ) with code sandbox.
What I did was to create a simple styled component on index.js (I'm not proficient with ts) and the error will show.
- Fork https://github.com/mui-org/material-ui/tree/75f27074b89381d25a1fab85fc2098af58e89cb0/examples/nextjs-with-styled-components-typescript
- Create a simple styled component
- Restart server (if you are using codesandbox).
- See console for error.
I've done the above in a sandbox - https://codesandbox.io/s/jolly-yonath-kjxj2?file=/pages/index.js
Context 🔦
I'm using NextJS but I'm not sure how to modify your example to work with Material-ui v5. I think this is the toughest part using NextJS + Material-UI and a solution is necessary.
Your Environment 🌎
`Material-UI`
"@material-ui/core": "^5.0.0-beta.2", "@material-ui/icons": "^5.0.0-beta.1", "@material-ui/lab": "^5.0.0-alpha.41", "@material-ui/styled-engine-sc": "^5.0.0-beta.1", "@material-ui/styles": "^5.0.0-beta.2",`NEXT.JS`
"next-transpile-modules": "^8.0.0", "next": "^11.0.1",`npx @material-ui/envinfo`
System:
OS: macOS 11.4
Binaries:
Node: 16.5.0 - ~/.nvm/versions/node/v16.5.0/bin/node
Yarn: Not Found
npm: 7.19.1 - ~/.nvm/versions/node/v16.5.0/bin/npm
Browsers:
Chrome: 92.0.4515.107
Edge: Not Found
Firefox: Not Found
Safari: 14.1.1
Agree, I don't think that we can expect developers to use the current version of the example. Personally, I wouldn't as it not really working.
~https://github.com/mui-org/material-ui/pull/27088#issuecomment-885278495 is a working solution.~
As to why the current solution doesn't work? I don't know. It would be great to have a deep dive. So far, it seems that styled-components was not designed for SSR.
Thanks @oliviertassinari
I've tried your linked solution. I've removed the webpack config for alias, and updated package.json with
"@material-ui/styled-engine": "npm:@material-ui/styled-engine-sc@next"
It seems to have removed the className mismatch error.
However, for your information. I cannot remove the next-transpile-modules
( per your example ) in my projects.
Since MUI v5, I've been experiencing the following error if I don't use the next-transpile-modules. It says export is undefined.
I haven't tested enough to know whether I'm the only one needing the transpile, or whether it's really Mui related.
index.js?20a9:42 Uncaught at /Users/myname/Work/React/myproject/node_modules/ (material-ui/core/colors/grey.js:17)
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1025:15)
at Module._compile (node:internal/modules/cjs/loader:1059:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1124:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:816:12)
at Module.require (node:internal/modules/cjs/loader:999:19)
at require (node:internal/modules/cjs/helpers:93:18)
at Object.@material-ui/core/colors/grey (file:///Users/myname/Work/React/myproject/.next/server/pages/component.js:515:18)
at __webpack_require__ (file:///Users/myname/Work/React/myproject/.next/server/webpack-runtime.js:33:42)
@daveteu Do you have a reproduction?
I am reopening as I needed to revert https://github.com/mui-org/material-ui/pull/27583 as it does not work with npm
. We'll come back to this later.
For those using yarn
https://github.com/mui-org/material-ui/pull/27583 should work and fix the class name mismatch error.
I also faced this issue recently with Next Js version 11.1.2 for some components.
But I was able to overcome the issue using the dynamic imports used by Next Js with ssr:false
Material UI version
"@material-ui/core": "5.0.0-beta.4", "@material-ui/icons": "5.0.0-beta.4", "@material-ui/lab": "5.0.0-alpha.43", "@material-ui/styles": "5.0.0-beta.4",
Styled Component version
"styled-components": "^5.3.1"
npx @material-ui/envinfo
System: OS: macOS 11.5.2 Binaries: Node: 14.17.0 - /usr/local/bin/node Yarn: 1.22.11 - /usr/local/bin/yarn npm: 7.20.1 - /usr/local/bin/npm Browsers: Chrome: 92.0.4515.159 Edge: Not Found Firefox: 90.0.2 Safari: 14.1.2
As i mentioned in closed issue above, in a builded app these errors does not exists, but i faced some components rendering issues, like Tabs.
In development environmnent the application crashes in every refresh, throwing this warning, the unique workarround that i found is using next/dynamic in every MUI component with SSR set to false, but, with this we loss the server side goods.
import dynamic from 'next/dynamic'
const Grid = dynamic(() => import('@mui/material/Grid'), { ssr: false })
For me on npm: '7.21.0'
just putting this in package.json
worked in dev and prod without any errors:
"dependencies": {
"@mui/material": "^5.0.0",
"@mui/icons-material": "^5.0.0",
"@mui/lab": "^5.0.0-alpha.47",
"@mui/styled-engine-sc": "^5.0.0",
"@mui/styles": "^5.0.0",
...,
"next": "^11.1.2",
...
"styled-components": "^5.3.1",
},
"alias": {
"@mui/styled-engine": "@mui/styled-engine-sc"
},
(and also having usual collectStyles
in the _document
and like 3 providers in the _app
)
I'm styling with import styled from "styled-components";
.
For me on
npm: '7.21.0'
just putting this inpackage.json
worked in dev and prod without any errors:"dependencies": { "@mui/material": "^5.0.0", "@mui/icons-material": "^5.0.0", "@mui/lab": "^5.0.0-alpha.47", "@mui/styled-engine-sc": "^5.0.0", "@mui/styles": "^5.0.0", ..., "next": "^11.1.2", ... "styled-components": "^5.3.1", }, "alias": { "@mui/styled-engine": "@mui/styled-engine-sc" },
(and also having usual
collectStyles
in the_document
and like 3 providers in the_app
)I'm styling with
import styled from "styled-components";
.
Warning: Did not expect server HTML to contain a <style> in <div>.
In every page refresh
Warning: Did not expect server HTML to contain a <style> in <div>.
In every page refresh
Putting "alias" in the package.lock surely wouldn't cause that.
Warning: Did not expect server HTML to contain a <style> in <div>.
In every page refreshPutting "alias" in the package.lock surely wouldn't cause that.
Is already in package.json, there's also in next.config.js the configs from examples.
webpack: config => {
config.resolve.alias = {
...config.resolve.alias,
'@mui/styled-engine': '@mui/styled-engine-sc'
}
return config
}
Already deleted .next and node_modules, cleaned up the browsers data and didn't solve this issue.
@mnajdova Is this still active or was it fixed in https://github.com/mui-org/material-ui/pull/27583?
Guys, I have edit sandbox example, because it doesn't reproduce bug. To reproduce bug, styled component must use props
Here is a link to see the bug
https://codesandbox.io/s/charming-rain-oswex?file=/pages/index.js
the same thing to withStyle and makeStyle If u dont use props, it is ok, but once u have used props based styles, bug happens
Hi guys, anyone figured out a fix?
https://github.com/mui-org/material-ui/tree/master/examples/nextjs-with-styled-components-typescript has some recents commit, still seeing the errors when developing
@alexhhn see https://github.com/mui-org/material-ui/issues/27512#issuecomment-903781107 If you are using yarn
- #27583 should work and fix the class name mismatch error. It, however, doesn't work with npm.
dunno if this is some poor hack or what, but i found solution that works for me:
_app.tsx:
export default function MyApp(props: AppProps) {
const { Component, pageProps } = props;
const [loaded, setLoaded] = React.useState(false);
React.useEffect(() => {
setLoaded(true);
}, []);
return (
<React.Fragment>
<Head>
<title>Next App</title>
<link href="/favicon.ico" rel="icon" />
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
{loaded && <Component {...pageProps} />}
</ThemeProvider>
</React.Fragment>
);
}
The problem with this approach is that the SSR part ends up being turned off @Michal-gasiorowski, I'm having the same problem using next + material-5 + makeStyles + npm, I saw several issues reporting this type of issue being caused by various reasons, this ended up leaving me confused about the real status of this issue?
Thats true @tiagooliveira08, i know its a temporary solution, not a proper fix, but i found that you can do this like below, and loose that ssr performance boost only in development- in production everything seems to work fine, and some quick tests i did shows, that ssr works fine in production without errors. But maybe, there is something im missing here, or other drawbacks?:
_app.tsx:
const isProd = process.env.NEXT_PUBLIC_ISPROD ? (process.env.NEXT_PUBLIC_ISPROD === "true" ? true : false) : true;
const MyApp: React.FC<AppProps> = (props) => {
const { Component, pageProps } = props;
const [loaded, setLoaded] = React.useState(false);
React.useEffect(() => {
setLoaded(true);
}, []);
return (
<React.Fragment>
<Head>
<title>Next App</title>
<link href="/favicon.ico" rel="icon" />
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
{(isProd || loaded) && <Component {...pageProps} />}
</ThemeProvider>
</React.Fragment>
);
};
export default MyApp;
envs:
NEXT_PUBLIC_ISPROD=false // dev
NEXT_PUBLIC_ISPROD=true // prod
ps. i dont like this soulution, but i havent found any better ;) All the fixes i found here and there, doesnt work with newest next.js + mui 5 + styled components
@alexhhn see #27512 (comment) If you are using
yarn
- #27583 should work and fix the class name mismatch error. It, however, doesn't work with npm.
For me, using yarn, this doesn't fix the issue right now.
Here is repro (though there isn't much to look at):
https://codesandbox.io/s/classmismatch-mui-2021-10-19-x27lr?file=/pages/index.tsx
Because it uses yarn 2, you'll need to open up second terminal and write yarn dev
(and probably yarn install
)
Sometimes codesandbox doesn't trigger the message immideately, local build is more "reliable"
@MonstraG we haven't tested with yarn 2 yet. Could you confirm that it works with 1?
Also having this problem, getting Prop 'className' did not match. Server: "sc-iktFfs ljFsjP sc-jJEKmz gpmJvp" Client: "sc-hHfuMS ixscoD sc-dmlqKv iyJBXp"
when using "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest"
and all the changes listed in https://github.com/mui-org/material-ui/pull/27583. I'm using import { styled } from "@mui/material/styles";
to style the components if that makes any difference, and yarn v2.
Hi again! I was able to get it working with yarn v2.
Followed the implementation in https://github.com/mui-org/material-ui/pull/27583 until I got the problem above, but I solved that problem by upgrading babel-plugin-styled-components
to v1.13.3
, and it seems to solve the problem overall. Cannot see any warnings any more!
Thanks for the info @JacobSoderblom, I will test again now to see if the instructions in #27583 still apply. We use there latest
as a version of the plugin so it should be always up to date.
Yarn2, recent update fixed important issue on production (thanks, by the way :) ), but classMismatch didn't go away. setup:
"@mui/material": "^5.0.6",
"@mui/styled-engine-sc": "^5.0.4",
and
"resolutions": {
"@mui/styled-engine": "npm:@mui/[email protected]"
},
import styled, { css } from "@mui/styled-engine";
switching to yarn1 does nothing.
@mnajdova, I'm still unsure of how to tackle the issue but it is worth mentioning that the issue is the same, following both, styled-components
and emotion
examples.
Detailed steps to reproduce:
-
(Terminal) Clone any of the available examples of nextjs + mui + typescript, (emotion or styled-components)
-
(Terminal) Install dependencies:
yarn
-
(Terminal) Add
@mui/styles
dependency to usemakeStyles
:yarn add @mui/styles
-
(/pages/index) Import makeStyles and define
classes
:- ps: using media queries here since breakpoints + typescript + useStyles was leading to another error;
// pages/index.tsx import Box from '@mui/material/Box'; import Container from '@mui/material/Container'; import Typography from '@mui/material/Typography'; import { makeStyles } from '@mui/styles'; import * as React from 'react'; import Copyright from '../src/Copyright'; import Link from '../src/Link'; import ProTip from '../src/ProTip'; export default function Index() { const classes = makeStyles(() => ({ container: { '@media (max-width: 600px)': { fontSize: 20'vw' }, '@media (min-width: 601px)': { fontSize: '7rem' } } }))(); return ( <Container maxWidth="sm" className={classes.container}> <Box sx={{ my: 4 }}> <Typography variant="h4" component="h1" gutterBottom> Next.js v5-beta with TypeScript example </Typography> <Link href="/about" color="secondary"> Go to the about page </Link> <ProTip /> <Copyright /> </Box> </Container> ); }
- (Terminal) Run project:
yarn dev
- (Browser) Access app on
http://localhost:3000
; - (Browser: DevTools) Set window to
responsive
and drag to force the media query responsive font size changes; - (Browser) :heavy_check_mark: Verify that it is all running as expected ;
- (Browser) Click on 'Go to the about page' link;
- (Browser) :heavy_check_mark: Verify that is all running as expected;
- (Browser) Click to go back on the browser 'back' arrow;
- (Browser) Refresh the page (F5);
- (Browser) ❌ Verify that the style broke and the following error appear on the console:
Warning: Prop `className` did not match. Server: "MuiContainer-root MuiContainer-maxWidthSm makeStyles-container-2 css-cuefkz-MuiContainer-root" Client: "MuiContainer-root MuiContainer-maxWidthSm makeStyles-container-1 css-cuefkz-MuiContainer-root" at div at eval (webpack-internal:///./node_modules/@emotion/react/dist/emotion-element-99289b21.browser.esm.js:55:66) at Container (webpack-internal:///./node_modules/@mui/material/Container/Container.js:93:83) at Index (webpack-internal:///./pages/index.tsx:32:19) at InnerThemeProvider (webpack-internal:///./node_modules/@mui/system/esm/ThemeProvider/ThemeProvider.js:21:70) at ThemeProvider (webpack-internal:///./node_modules/@mui/private-theming/ThemeProvider/ThemeProvider.js:47:5) at ThemeProvider (webpack-internal:///./node_modules/@mui/system/esm/ThemeProvider/ThemeProvider.js:41:5) at MyApp (webpack-internal:///./pages/_app.tsx:57:27) at StyleRegistry (webpack-internal:///./node_modules/styled-jsx/dist/stylesheet-registry.js:231:34) at ErrorBoundary (webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ErrorBoundary.js:26:47) at ReactDevOverlay (webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ReactDevOverlay.js:90:23) at Container (webpack-internal:///./node_modules/next/dist/client/index.js:305:9) at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:745:26) at Root (webpack-internal:///./node_modules/next/dist/client/index.js:866:27) printWarning @ react-dom.development.js?ac89:67 error @ react-dom.development.js?ac89:43 warnForPropDifference @ react-dom.development.js?ac89:8824 diffHydratedProperties @ react-dom.development.js?ac89:9645 hydrateInstance @ react-dom.development.js?ac89:10400 prepareToHydrateHostInstance @ react-dom.development.js?ac89:14616 completeWork @ react-dom.development.js?ac89:19458 completeUnitOfWork @ react-dom.development.js?ac89:22815 performUnitOfWork @ react-dom.development.js?ac89:22787 workLoopSync @ react-dom.development.js?ac89:22707 renderRootSync @ react-dom.development.js?ac89:22670 performSyncWorkOnRoot @ react-dom.development.js?ac89:22293 scheduleUpdateOnFiber @ react-dom.development.js?ac89:21881 updateContainer @ react-dom.development.js?ac89:25482 eval @ react-dom.development.js?ac89:26021 unbatchedUpdates @ react-dom.development.js?ac89:22431 legacyRenderSubtreeIntoContainer @ react-dom.development.js?ac89:26020 hydrate @ react-dom.development.js?ac89:26086 renderReactElement @ index.js?46cb:488 doRender @ index.js?46cb:709 _callee$ @ index.js?46cb:384 tryCatch @ runtime.js?2d8a:45 invoke @ runtime.js?2d8a:274 prototype.<computed> @ runtime.js?2d8a:97 asyncGeneratorStep @ index.js?46cb:31 _next @ index.js?46cb:49 eval @ index.js?46cb:54 eval @ index.js?46cb:46 _render @ index.js?46cb:403 render @ index.js?46cb:406 eval @ next-dev.js?3515:76 eval @ fouc.js?0087:12 requestAnimationFrame (async) displayContent @ fouc.js?0087:7 eval @ next-dev.js?3515:75 Promise.then (async) eval @ next-dev.js?3515:38 ./node_modules/next/dist/client/next-dev.js @ main.js?ts=1635690486095:578 options.factory @ webpack.js?ts=1635690486095:633 __webpack_require__ @ webpack.js?ts=1635690486095:37 __webpack_exec__ @ main.js?ts=1635690486095:1247 (anonymous) @ main.js?ts=1635690486095:1248 webpackJsonpCallback @ webpack.js?ts=1635690486095:1179 (anonymous) @ main.js?ts=1635690486095:9 Show 2 more frames
My environment:
node: v16.13.0 yarn: v1.22.10
After struggling for a day with a combination of issues (Next.js 12 + MUI v5 + TypeScript + makeStyles), I guess there is a permanent solution (at least for those using emotion as engine and are wiling to use styled
api). I think it also works with styled components but can't be sure since I ran into another error (same mentioned by @mnajdova here);
So... to the possible solution:
While trying to fix the media query thing, I stumbled upon this CodeSandbox, that uses the styled
API instead of makeStyles
. I also noticed that it uses a <StyledEngineProvider>
component with injectFirst
property, but after testing it, the use of styled
API was enough to prevent the issue.
I will send a PR, adding a styled component to the the emotion example in the next minutes (my first PR here, still unsure of how to proceed, but I'll give it a try), so that other people can also avoid wasting time on the makeStyles
path.
_document.tsx
`import { ServerStyleSheets } from '@mui/styles'
MyDocument.getInitialProps = async (ctx) => { const sheets = new ServerStyleSheets() ctx.renderPage = () => originalRenderPage({ // eslint-disable-next-line react/display-name enhanceApp: (App: any) => (props) => sheets.collect(<App emotionCache={cache} {...props} />), }) ..... return { ...initialProps, // Styles fragment is rendered after the app and page rendering finish. styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()], } }`
@mnajdova Thanks for the answer, I tried to use Yarn but still got the same error after one refresh
See https://github.com/mui-org/material-ui/issues/29742#issuecomment-982597676 I am starting to think that we should maybe rather recommend emotion for SSR projects. There are just so many issues using styled-components
with external library.
Credits to @Janpot for the investigation around this.
See #29742 (comment) I am starting to think that we should maybe rather recommend emotion for SSR projects. There are just so many issues using
styled-components
with external library.Credits to @Janpot for the investigation around this.
I'm a styled-component user with NextJS. Can we conveniently convert to emotion just by updating the _document.js as specified in the example repo?
Our components are all using the const Styledcomponent = styled(MuiComponent)(({ theme }) => ``)
pattern.
We are uncomfortable with moving our codes now because we do not understand why Mui offers the choice of "emotion" and "styled-components" and we used "styled-components" simply because we have used it before and we can easily reuse many of our component codes.
However, in your https://codesandbox.io/s/9r5ww?file=/demo.js example sandbox, it uses @emotion/styled and it looks the same as styled-components code style.
Also, in the documentation, there is also 'styled component API' https://mui.com/styles/basics/#styled-components-api which we are unsure whether it's related to using 'styled-components, or Mui simply created a API that allow us to create styles using styled-components code style.
overall it's a little confusing... will there be a lot of code migration if we switch to emotion now?