Skip to content

ClassName generator not working with Next.js App router #45128

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

Closed
NotYoojun opened this issue Jan 27, 2025 · 14 comments · Fixed by #45852
Closed

ClassName generator not working with Next.js App router #45128

NotYoojun opened this issue Jan 27, 2025 · 14 comments · Fixed by #45852
Assignees
Labels
docs Improvements or additions to the documentation nextjs package: material-ui Specific to @mui/material package: utils Specific to the @mui/utils package

Comments

@NotYoojun
Copy link

NotYoojun commented Jan 27, 2025

Steps to reproduce

Steps:

  1. Open this link to live example: click here
  2. npm run dev
  3. Open the devtools and inspect the element tree

Current behavior

All the class names stay unchanged:

Image

Expected behavior

All class names should be transformed by the ClassNameGenerator.

Context

I also tried to import the 'init-cls.ts' as a client script, but that only affects the client side, and the server side is just doing nothing.
I'm following this doc: https://mui.com/material-ui/experimental-api/classname-generator/

Your environment

System:
OS: Linux 6.1 Debian GNU/Linux 12 (bookworm) 12 (bookworm)
Binaries:
Node: 20.9.0 - /usr/local/bin/node
npm: 9.8.1 - /usr/local/bin/npm
pnpm: 8.10.2 - /usr/local/share/npm-global/bin/pnpm
Browsers:
Chrome: Not Found
npmPackages:
@emotion/react: latest => 11.11.1
@emotion/styled: latest => 11.11.0
@mui/core-downloads-tracker: 6.0.0
@mui/icons-material: latest => 6.0.0
@mui/material: latest => 6.0.0
@mui/material-nextjs: latest => 6.0.0
@mui/private-theming: 6.0.0
@mui/styled-engine: 6.0.0
@mui/system: 6.0.0
@mui/types: 7.2.16
@mui/utils: 6.0.0
@types/react: ^19.0.0 => 19.0.2
react: ^19.0.0 => 19.0.0
react-dom: ^19.0.0 => 19.0.0
typescript: latest => 5.1.6

Search keywords: next, nextjs, app, classname, styles, experimental, css, class

@NotYoojun NotYoojun added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jan 27, 2025
@zannager zannager added package: system Specific to @mui/system nextjs labels Jan 27, 2025
@NotYoojun
Copy link
Author

Anyone looking into this? please

@aarongarciah
Copy link
Member

Hi @NotYoojun, the CodeSandbox link is broken. Can you share a reproduction?

@NotYoojun
Copy link
Author

@aarongarciah Hi, what about this one?
https://codesandbox.io/p/devbox/mre-mui-cssclassgenerator-next-appdir-dp4zz2

@aarongarciah aarongarciah added package: material-ui Specific to @mui/material package: utils Specific to the @mui/utils package and removed package: system Specific to @mui/system labels Feb 11, 2025
@aarongarciah
Copy link
Member

@NotYoojun that sandbox works. We still not have a guide for Next.js App router specifically (and React Server Components in general) in the docs.

@siriwatknp is there a recommendation? It kinda works if you import the class name generator module in page.tsx instead of layout.tsx, but it's obviously not a good solution (the "entry" point is layout.tsx, but it's a RSC) and it's buggy: it duplicates the prefix in the Box component (probably calls twice the generator function). See this sandbox: https://codesandbox.io/p/devbox/mre-mui-cssclassgenerator-next-appdir-forked-mcj7gm?workspaceId=ws_TYgwg9BhnaH6MHvmXJ1vH9

@aarongarciah aarongarciah added bug 🐛 Something doesn't work and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Feb 11, 2025
@NotYoojun
Copy link
Author

Well, to add it into page.tsx will force developers to import that thing on EVERY PAGE, which is not really a good solution :(
I tried this in my own project, and there seemed to be a lot of weird issues

@aarongarciah
Copy link
Member

to add it into page.tsx will force developers to import that thing on EVERY PAGE

@NotYoojun yeah, that's what I meant by "it's obviously not a good solution (the 'entry' point is layout.tsx". It also doesn't work well so let's wait for @siriwatknp to see if there's a proper solution.

@Janpot
Copy link
Member

Janpot commented Feb 13, 2025

@NotYoojun You need two things:

  1. The MUI components are client components, so the ClassNameGenerator needs to be initialized on the client. Add 'use client'; to the ./initialize-mui.ts module
  2. There seems to be a bug in Next.js which filters client modules from layout pages. Workaround would be to export something (export default null;) from the ./initialize-mui.ts and import and render it in the layout page.

Codesandbox with a fix.

@NotYoojun
Copy link
Author

NotYoojun commented Feb 14, 2025

@Janpot Thks for the workaround, it works! However, this is making the classes objects (e.g. buttonClasses) got initialized before the classname configuration if the component contains a MUI component is used in the layout.tsx. I know this sounds complex, so here's the sandbox:

https://codesandbox.io/p/devbox/mre-mui-cssclassgenerator-next-appdir-forked-9pv2l4?workspaceId=ws_LFCUAYD9gBTdMJ7CyS3vBj

It is supposed to be 'test-button-root', but the actual result is still the old one.

Image

This only happens in client side and retriving the name from import { buttonClasses } from "@mui/material/Button". It seems that the rendered elements are working, just the strings from 'buttonClasses' are not correct.

@aarongarciah
Copy link
Member

@NotYoojun true. What comes from the server is correct but upon hydration the wrong class name is used. There's an hydration error because of this. You can see the class name flickering when refreshing.

@NotYoojun
Copy link
Author

@aarongarciah Yeah I can see that, but how to fix this? I observed that on the client side the class names are generated before the configuration script is executed. On the server side, the situation is exactly the opposite, which is correct.

@aarongarciah
Copy link
Member

@NotYoojun we'll have a look cc @siriwatknp

@siriwatknp
Copy link
Member

siriwatknp commented Apr 9, 2025

Move the import to page.tsx fixes the issue.
https://codesandbox.io/p/devbox/mre-mui-cssclassgenerator-next-appdir-janport-forked-43mq9s

I mark this as docs improvement.

@siriwatknp siriwatknp added docs Improvements or additions to the documentation and removed bug 🐛 Something doesn't work labels Apr 9, 2025
@github-project-automation github-project-automation bot moved this from Selected to Done in Material UI public roadmap Apr 10, 2025
Copy link

This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue.
Now, if you have additional information related to this issue or things that could help future readers, feel free to leave a comment.

@NotYoojun
Copy link
Author

Move the import to page.tsx fixes the issue. https://codesandbox.io/p/devbox/mre-mui-cssclassgenerator-next-appdir-janport-forked-43mq9s

I mark this as docs improvement.

This is not a good idea. since you don't know which page the user will go first. If we have to put the directive on EVERY page, it will be destructive and sometimes cause mistakes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to the documentation nextjs package: material-ui Specific to @mui/material package: utils Specific to the @mui/utils package
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

5 participants