Material-ui: generateClassName is not working for NextJS

Created on 14 Sep 2019  ยท  11Comments  ยท  Source: mui-org/material-ui

  • [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 ๐Ÿ˜ฏ

When the generateClassName is used, it is not applied to the server rendered style sheets. It is only applied for the client side.

Expected Behavior ๐Ÿค”

The class names are changed according to the generateClassName for both server side and client side.

Steps to Reproduce ๐Ÿ•น

Codesandbox: https://codesandbox.io/embed/github/kamalarieff/nextjs-mui-cls/tree/master/
Repo: https://github.com/kamalarieff/nextjs-mui-cls.git

I've added the StylesProvider as such. However, when I view the page source, I can't find my new class prefix anywhere:

Screen Shot 2019-09-14 at 5 05 27 PM

But when I do inspect element, I can find it:

Screen Shot 2019-09-14 at 5 09 16 PM

It seems like class name generator is applied to client side only.

My suspicion is that the instance of the class name generator is not the same for SSR and CSR but I don't know how to confirm this.

Solutions I've tried:

  1. https://material-ui.com/styles/api/#new-serverstylesheets-options
  2. Adding NODE_ENV=production to both the build and start step according to this issue
  3. Removing the
    js ctx.renderPage = () => originalRenderPage({ enhanceApp: App => props => sheets.collect(<App {...props} />), });
    from pages/_document.js. This worked but there was a flash of unstyled content. There's also no documentation regarding enhanceApp so I wasn't sure about this implementation.
  4. Using the seed property works but there was also a flash of unstyled content.

Context ๐Ÿ”ฆ

We have a separate package that provides react components and they are built with material ui. When I import this component into our app, their class names are conflicting with each other.

Your Environment ๐ŸŒŽ

This repo was cloned from https://github.com/mui-org/material-ui/tree/master/examples/nextjs.

Dependencies:

"@material-ui/core": "latest",
"@material-ui/styles": "latest",
"clsx": "latest",
"next": "latest",
"prop-types": "latest",
"react": "latest",
"react-dom": "latest"
styles

Most helpful comment

You also need to apply the custom generator on the server-side:

_document.js

  const generateClassName = createGenerateClassName({
    productionPrefix: "yoghirt"
  });

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets({
    serverGenerateClassName: generateClassName
  });

All 11 comments

๐Ÿ‘

You also need to apply the custom generator on the server-side:

_document.js

  const generateClassName = createGenerateClassName({
    productionPrefix: "yoghirt"
  });

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets({
    serverGenerateClassName: generateClassName
  });

@oliviertassinari Awesome now it works. But I have a different issue now. After the app has been mounted, the server side style sheets are removed. But this only happens in my project though not the example project. Could one of the node_modules be affecting this?

@kamalarieff The server-side styles are meant to be removed, so the client can inject them back.

@oliviertassinari I see. So does that mean the client is injecting partially empty styles?

I found the issue. The styles disappear when I connect the application to redux.

I'm able to replicate the issue here.

I've found the solution. For anyone reading, here it is.

Here's the repo for good measure.

@oliviertassinari the serverGenerateClassName was not mentioned in the docs. Might be a good idea to include them for future devs.

I've found the solution. For anyone reading, here it is.

Here's the repo for good measure.

@oliviertassinari the serverGenerateClassName was not mentioned in the docs. Might be a good idea to include them for future devs.

@oliviertassinari Thanks, I really think the serverGenerateClassName needs to be documented. I spent an hour looking for this. The docs suggest that options should be sent like for StylesProvider. Thank you for the lib by the way :)

serverGenerateClassName

Should add it to the document ๐Ÿ‘€

๐Ÿคฃ really should add it to the document, wasted another 10 minutes today

Important thing is that don't use the same instance of generateClassName on client and server

wrong โŒ

const classPrefix = "my-prefix";
const generateClassName = createGenerateClassName({
    seed: classPrefix,
});

...
<StylesProvider generateClassName={generateClassName}>..</StylesProvider>

// on server
new ServerStyleSheets({
    serverGenerateClassName: generateClassName,
});

correct โœ…

const classPrefix = "my-prefix";
const generateClassName = () => createGenerateClassName({
    seed: classPrefix,
});

...
<StylesProvider generateClassName={generateClassName()}>..</StylesProvider>

// on server
new ServerStyleSheets({
    serverGenerateClassName: generateClassName(),
});

More here

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pola88 picture pola88  ยท  3Comments

rbozan picture rbozan  ยท  3Comments

TimoRuetten picture TimoRuetten  ยท  3Comments

reflog picture reflog  ยท  3Comments

ghost picture ghost  ยท  3Comments