Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next.js + Material UI v5 styled-component example is still showing className mismatch error #27512

Open
daveteu opened this issue Jul 29, 2021 · 53 comments · Fixed by #27583
Open
Labels
bug 🐛 Something doesn't work external dependency Blocked by external dependency, we can’t do anything about it nextjs package: styled-engine-sc Specific to styled-components priority: important This change can make a difference

Comments

@daveteu
Copy link

daveteu commented Jul 29, 2021

  • [ 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.

  1. Fork https://github.com/mui-org/material-ui/tree/75f27074b89381d25a1fab85fc2098af58e89cb0/examples/nextjs-with-styled-components-typescript
  2. Create a simple styled component
  3. Restart server (if you are using codesandbox).
  4. 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
@daveteu daveteu added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jul 29, 2021
@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 29, 2021

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.

#27088 (comment) 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.

@daveteu
Copy link
Author

daveteu commented Jul 30, 2021

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)

@oliviertassinari
Copy link
Member

@daveteu Do you have a reproduction?

@eps1lon eps1lon added bug 🐛 Something doesn't work package: styled-engine Specific to @mui/styled-engine and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Aug 2, 2021
@oliviertassinari oliviertassinari removed the package: styled-engine Specific to @mui/styled-engine label Aug 3, 2021
@mnajdova mnajdova reopened this Aug 23, 2021
@mnajdova
Copy link
Member

I am reopening as I needed to revert #27583 as it does not work with npm. We'll come back to this later.

For those using yarn #27583 should work and fix the class name mismatch error.

@oliviertassinari oliviertassinari added the package: styled-engine-sc Specific to styled-components label Aug 24, 2021
@ankurmaheshsingh
Copy link

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

@truediogo
Copy link

truediogo commented Sep 16, 2021

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 })

@MonstraG
Copy link
Contributor

MonstraG commented Sep 17, 2021

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";.

@truediogo
Copy link

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";.

Warning: Did not expect server HTML to contain a <style> in <div>.

In every page refresh

@MonstraG
Copy link
Contributor

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.

@truediogo
Copy link

truediogo commented Sep 17, 2021

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.

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.

@eps1lon
Copy link
Member

eps1lon commented Sep 18, 2021

@mnajdova Is this still active or was it fixed in #27583?

@nurbeknurjanov
Copy link

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

@gajet5

This comment was marked as off-topic.

@alexhhn
Copy link

alexhhn commented Sep 29, 2021

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

@mnajdova
Copy link
Member

@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.

@Michal-gasiorowski
Copy link

Michal-gasiorowski commented Oct 18, 2021

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>
  );
}

@oxwazz
Copy link

oxwazz commented Jan 21, 2022

its not recommend if you use makeStyle on Mui V5.

because the docs said : https://mui.com/styles/basics/#main-content

recommented using style() / css API instead of makeStyle (@mui/styles)

import * as React from "react";
import Typography from "@mui/material/Typography";
import { css } from "@emotion/react";
import { useTheme } from "@mui/material/styles";

export default function MiniDrawer() {
  const theme = useTheme();

  const classes = React.useMemo(
    () => ({
      titleAppbar: css`
        color: ${theme.palette.customColor.blue};
      `,
    }),
    []
  );

  return (
    <Typography css={classes.titleAppbar} variant="h6" noWrap component="div" > 
        Mini variant drawer
     </Typography>
  )
}

@Michal-gasiorowski
Copy link

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>
  );
}

This is good solution when working in dev, but it's unfortunate to have to include this when the issue doesn't present itself when the bundle is built.

Thats why i posted another solution, few posts below, that uses that approach and omit it completely when the bundle is built (using envs), as the issue seems not to appear on production build. Im using this approach since then without issues, and i can still use SSR on production.

@SalahAdDin

This comment was marked as off-topic.

@mnajdova

This comment was marked as off-topic.

@mnajdova mnajdova added the external dependency Blocked by external dependency, we can’t do anything about it label Jun 1, 2022
@SalahAdDin

This comment was marked as off-topic.

@oliviertassinari

This comment was marked as off-topic.

@oliviertassinari oliviertassinari changed the title Nextjs + Mui V5 styled-component example is still showing className mismatch error Next.js + Mui V5 styled-component example is still showing className mismatch error Jun 1, 2022
@oliviertassinari oliviertassinari changed the title Next.js + Mui V5 styled-component example is still showing className mismatch error Next.js + Material UI v5 styled-component example is still showing className mismatch error Jun 1, 2022
@zachsa
Copy link

zachsa commented Jul 12, 2022

I had two deployments of the same app. When NODE_ENV was set to production this error occurred, whereas on my localhost and in a dev environment it didn't happen.

Debugging this I found that in my production environment I was getting the dev version of react, because I wasn't threading NODE_ENV through my deployment steps correctly.

In my case I am using import maps in the client and for the server-side rendering, I think that having NODE_ENV set to 'production' in my Node.js server, but rendering React SSR from the development import of React may have been causing this. But can't be sure.

@TurkaljGoran
Copy link

TurkaljGoran commented Jul 19, 2022

This might be a solution:

My example component:

image

When import {styled} from "@mui/material/styles" is used there is mismatch AND no displayName on classes (just generic class names are there):
image

When import styled from "styled-components" is used there is NO mismatch and displayName on classes is shown properly (component name + generic part of the class name):

image

Now the question is - will using 'import styled from "styled-components" ' instead of 'import {styled} from "@mui/material/styles"' cause any other problems?

So far the mismatch is gone, MUI theme is acessible in the component I styled, SSR is working properly, I can build the project.

Will this approach bite us in the ass later on somewhere?
What is tradeoff between using styled from MUI vs styled from styled-components directly but with MUI theme?

EDIT:

  1. No more Typescript suggesting color names and other theme properties when styling. - I suspect this can be fixed.
    This is fixed by extending DefaultTheme of styled-components with Theme interface from MUI, in your theme.ts file

declare module 'styled-components' {
export interface DefaultTheme extends Theme {

}

}

EDIT 2: mismatch appears again IF actual MUI components are being used and it does not matter if styled is used from styled-components or MUI

so styled(Button)color: blue;
will result in a mismatch since MUI component Button is being used.

image

@IlanFrumer
Copy link

Our temporary solution until we will migrate from makeStyles

import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import { lightTheme } from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';
import { ServerStyleSheets } from '@mui/styles';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="iw" dir="rtl">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={lightTheme.palette.primary.main} />
          <link rel="shortcut icon" href="/static/favicon.ico" />
          {/* Inject MUI styles first to match with the prepend: true configuration. */}
          {(this.props as any).emotionStyleTags}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

MyDocument.getInitialProps = async (ctx) => {
  const originalRenderPage = ctx.renderPage;
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  const sheets = new ServerStyleSheets();

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App: any) =>
        function EnhanceApp(props) {
          return sheets.collect(<App emotionCache={cache} {...props} />);
        },
    });

  const initialProps = await Document.getInitialProps(ctx);
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    styles: [
      ...React.Children.toArray(initialProps.styles),
      sheets.getStyleElement(),
    ],
    emotionStyleTags,
  };
};

@SalahAdDin
Copy link

Our temporary solution until we will migrate from makeStyles

import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import { lightTheme } from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';
import { ServerStyleSheets } from '@mui/styles';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="iw" dir="rtl">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={lightTheme.palette.primary.main} />
          <link rel="shortcut icon" href="/static/favicon.ico" />
          {/* Inject MUI styles first to match with the prepend: true configuration. */}
          {(this.props as any).emotionStyleTags}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

MyDocument.getInitialProps = async (ctx) => {
  const originalRenderPage = ctx.renderPage;
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  const sheets = new ServerStyleSheets();

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App: any) =>
        function EnhanceApp(props) {
          return sheets.collect(<App emotionCache={cache} {...props} />);
        },
    });

  const initialProps = await Document.getInitialProps(ctx);
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    styles: [
      ...React.Children.toArray(initialProps.styles),
      sheets.getStyleElement(),
    ],
    emotionStyleTags,
  };
};

It is fun cause we are not using makeStyles.

@oalexdoda
Copy link

Still having this issue even with the latest examples. Any updates here?

@SalahAdDin

This comment was marked as resolved.

@daveteu

This comment was marked as resolved.

@SalahAdDin

This comment was marked as off-topic.

@oliviertassinari

This comment was marked as off-topic.

@SalahAdDin

This comment was marked as resolved.

@fundlg
Copy link

fundlg commented May 7, 2024

Does anyone have some updates on this issue?

@SalahAdDin
Copy link

Not solved yet?

@GustavoContreiras
Copy link

Deleting .next folder worked for me

@dms120
Copy link

dms120 commented Jul 4, 2024

This happens to me in development (next dev). If i run a production build (next build && next start) this is not reproducible.

@danieljmann96
Copy link

Deleting .next folder worked for me

Works for me too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work external dependency Blocked by external dependency, we can’t do anything about it nextjs package: styled-engine-sc Specific to styled-components priority: important This change can make a difference
Projects
None yet
Development

Successfully merging a pull request may close this issue.