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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[system] getInitColorSchemeScript, createTheme() shouldn't have "use client" #42750

Open
Tracked by #34905
oliviertassinari opened this issue Sep 16, 2023 · 15 comments
Open
Tracked by #34905
Assignees
Labels
bug 馃悰 Something doesn't work nextjs package: system Specific to @mui/system

Comments

@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 16, 2023

Steps to reproduce 馃暪

Link to live example:

Steps:

  1. Create a project with Next.js
  2. Add in the layout
import { getInitColorSchemeScript } from '@mui/material/styles';

  return (
    <html lang="en">
      <head>
        {getInitColorSchemeScript()}
      </head>

Current behavior 馃槸

Screenshot 2023-09-16 at 22 00 32

Expected behavior 馃

It works

Context 馃敠

Your environment 馃寧

npx @mui/envinfo
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.

Search keywords:

Search keywords:

@mj12albert
Copy link
Member

getInitColorSchemeScript does not have 'use client', but adding it back (PR) doesn't fix it 馃: https://stackblitz.com/edit/github-ppgum4-bxmkqa?file=src%2Fapp%2Flayout.tsx

@oliviertassinari
Copy link
Member Author

oliviertassinari commented Sep 24, 2023

@mj12albert I think that this is the opposite problem. There should be no 'use client' in the import path.

In today's import path, there are a good number of them:

then

then

@cyrilchapon
Copy link

Landed here after reproducing steps.
Any current workaround to avoid flickering while still using app folder and layout ?

@mnajdova mnajdova assigned mnajdova and unassigned mj12albert Nov 9, 2023
@ZeeshanTamboli ZeeshanTamboli removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Nov 15, 2023
@bartlangelaan
Copy link

As a workaround, it is possible to import from @mui/system/cssVars/getInitColorSchemeScript directly.

import { Experimental_CssVarsProvider } from "@mui/material";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter";
import getInitColorSchemeScript from "@mui/system/cssVars/getInitColorSchemeScript";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link
          rel="preconnect"
          href="https://fonts.gstatic.com"
          crossOrigin="anonymous"
        />
        <link
          rel="stylesheet"
          href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
        />
      </head>
      <body>
        <AppRouterCacheProvider>
          <Experimental_CssVarsProvider defaultMode="system">
            {getInitColorSchemeScript({
              // These properties are normally set when importing from @mui/material,
              // but we have to set manually because we are importing from @mui/system.
              attribute: "data-mui-color-scheme",
              modeStorageKey: "mui-mode",
              colorSchemeStorageKey: "mui-color-scheme",
              // All options that you pass to CssVarsProvider you should also pass here.
              defaultMode: "system",
            })}
            {children}
          </Experimental_CssVarsProvider>
        </AppRouterCacheProvider>
      </body>
    </html>
  );
}

It would be nice if this could be integrated in the @mui/material-nextjs package, so that the provider and getInitColorSchemeScript function are combined (and you only have to pass the options once).

@oliviertassinari oliviertassinari changed the title [system] getInitColorSchemeScript shouldn't have "use client" [system] getInitColorSchemeScript, createTheme() shouldn't have "use client" Jan 17, 2024
@oliviertassinari
Copy link
Member Author

oliviertassinari commented Jan 18, 2024

Same bug with createTheme. There is no reason I'm aware of for createTheme to not be used on the server:

Screenshot 2024-01-18 at 00 16 34

https://stackblitz.com/edit/github-z45nfe-5k5dkz?file=src%2Fapp%2Fpage.tsx,src%2Fapp%2Flayout.tsx,src%2Ftheme.ts

I first saw a developer complain on Twitter, more recently on #40199 (comment).

@jamietdavidson
Copy link

Following up from #40945 (the issue closed right above) - the recommended steps there did not work (still experiencing flickering). Will be following this issue for updates.

@siriwatknp
Copy link
Member

I'm on this. This should help with zero-runtime integration as well.

@siriwatknp siriwatknp assigned siriwatknp and unassigned mnajdova Feb 13, 2024
@oliviertassinari
Copy link
Member Author

I took a few steps to fix this in #40663 but didn't go all in. Wanted to test the water.

@siriwatknp
Copy link
Member

I got this error after removing use client directive from the index:

Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
  {keys: ..., values: ..., up: function, down: ..., between: ..., only: ..., not: ..., unit: ...}

I wonder if it would be a better DX to add use client to createTheme and related functions.

@oliviertassinari
Copy link
Member Author

oliviertassinari commented Feb 19, 2024

Functions cannot be passed directly to Client Components

@siriwatknp Arf, tricky.

It goes back to my point in: emotion-js/emotion#2978 (comment). The right solution might be to have two default themes/two theme creators: one in the client-side bundle and one in the server-side bundle. I mean, it would be the exact same logic, but one would be flagged as use client, the other wouldn't, so two different entry points, one implementation.

How I understand things working:

SCR-20240221-oups

@bestickley
Copy link

@bartlangelaan's workaround didn't work for me. Seems like it's not exported anymore. I've resorted to adding data-mui-color-scheme="dark" as an attribute in my top level <html> to get around the AppBar flickering between custom colors. This works for me since I'm only using dark mode. If there is a better way I'd be interested in knowing :)

@siriwatknp siriwatknp changed the title [system] getInitColorSchemeScript, createTheme() shouldn't have "use client" [system] getInitColorSchemeScript shouldn't have "use client" Mar 7, 2024
@siriwatknp
Copy link
Member

@oliviertassinari I'm removing createTheme() from the title. I think that createTheme() should have use client; to be used with Context.

@LikeDreamwalker
Copy link

As a workaround, it is possible to import from @mui/system/cssVars/getInitColorSchemeScript directly.

import { Experimental_CssVarsProvider } from "@mui/material";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter";
import getInitColorSchemeScript from "@mui/system/cssVars/getInitColorSchemeScript";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link
          rel="preconnect"
          href="https://fonts.gstatic.com"
          crossOrigin="anonymous"
        />
        <link
          rel="stylesheet"
          href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
        />
      </head>
      <body>
        <AppRouterCacheProvider>
          <Experimental_CssVarsProvider defaultMode="system">
            {getInitColorSchemeScript({
              // These properties are normally set when importing from @mui/material,
              // but we have to set manually because we are importing from @mui/system.
              attribute: "data-mui-color-scheme",
              modeStorageKey: "mui-mode",
              colorSchemeStorageKey: "mui-color-scheme",
              // All options that you pass to CssVarsProvider you should also pass here.
              defaultMode: "system",
            })}
            {children}
          </Experimental_CssVarsProvider>
        </AppRouterCacheProvider>
      </body>
    </html>
  );
}

It would be nice if this could be integrated in the @mui/material-nextjs package, so that the provider and getInitColorSchemeScript function are combined (and you only have to pass the options once).

Thanks and it works for me!

@eevloeev
Copy link

eevloeev commented Jun 9, 2024

The bug is still relevant

@oliviertassinari oliviertassinari transferred this issue from mui/material-ui Jun 9, 2024
@oliviertassinari oliviertassinari changed the title [system] getInitColorSchemeScript shouldn't have "use client" [system] getInitColorSchemeScript, createTheme() shouldn't have "use client" Jun 9, 2024
@oliviertassinari
Copy link
Member Author

oliviertassinari commented Jun 9, 2024

I think that createTheme() should have use client; to be used with Context.

@siriwatknp I would still expect the opposite. We need to be able to use the theme in server components, but also in client components. So I would expect that a theme is created twice.

@siriwatknp siriwatknp added this to the Material UI: v6 milestone Jun 25, 2024
@siriwatknp siriwatknp transferred this issue from mui/pigment-css Jun 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 馃悰 Something doesn't work nextjs package: system Specific to @mui/system
Projects
Status: Selected