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

Styles not applied in first loading correctly with NextJS #30410

Closed
2 tasks done
daniielp opened this issue Dec 26, 2021 · 35 comments
Closed
2 tasks done

Styles not applied in first loading correctly with NextJS #30410

daniielp opened this issue Dec 26, 2021 · 35 comments
Labels
examples Relating to /examples external dependency Blocked by external dependency, we can’t do anything about it package: system Specific to @mui/system

Comments

@daniielp
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

When using SX prop I seem to be getting an issue when deploying the application where a lot of the styles are loaded after the dom has rendered. Even though I use the emotion cache in my _documents.tsx, and create and use the theme in _app.tsx.

After my previous issue #29637 got closed because I also thought it solved the issue. I noticed on the live site that it's still an issue even after updating to SX prop.

Expected behavior 🤔

What should is that when rendering the page the first time all the style changes should already be there. but takes a small bit of time before it does.
https://imgur.com/a/ZujFrXd

Steps to reproduce 🕹

The issue is now only visible on the live site (Hosted with vercel).
https://daniiel.dev/

But for you want want to take a look or maybe have an idea what could cause it.

You can have a look at the repo and play around yourself by using the codesandbox bellow
codesandbox: https://codesandbox.io/s/hopeful-bush-5jbz8

Context 🔦

What I'm trying to accomplish is for my production build to look like my local development on initial load.

I think the issue lays in either the _documents.tsx or _app.tsx.

I have attached a link to the 2 images for how it looks in local development and production.
https://imgur.com/a/ZujFrXd

Your environment 🌎

Used both Firefox Developer Edition & Google Chrome (Version: 96.0.4664.110) for testing.

System:
OS: Windows 10 10.0.19044
Binaries:
Node: 16.13.1 - C:\Program Files\nodejs\node.EXE
Yarn: Not Found
npm: 8.1.2 - C:\Program Files\nodejs\npm.CMD
Browsers:
Chrome: Not Found
Edge: Spartan (44.19041.1266.0), Chromium (96.0.1054.62)
npmPackages:
@emotion/react: ^11.5.0 => 11.5.0
@emotion/styled: ^11.3.0 => 11.3.0
@mui/core: 5.0.0-alpha.53
@mui/lab: ^5.0.0-alpha.53 => 5.0.0-alpha.53
@mui/material: ^5.0.6 => 5.0.6
@mui/private-theming: 5.0.1
@mui/styled-engine: 5.0.2
@mui/system: 5.0.6
@mui/types: 7.0.0
@mui/utils: 5.0.1
@types/react: ^17.0.34 => 17.0.34
react: ^17.0.2 => 17.0.2
react-dom: ^17.0.2 => 17.0.2
typescript: ^4.3.5 => 4.3.5

--- tsconfig.json ---
{
"compilerOptions": {
"lib": [
"es6",
"dom"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"target": "es5",
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"/*.ts",
"
/*.tsx",
"src/components"
],
"exclude": [
"node_modules"
]
}

@daniielp daniielp added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 26, 2021
@siriwatknp
Copy link
Member

siriwatknp commented Dec 27, 2021

@shorcy Can you try the new _document.js in the our nextjs example? https://github.com/mui-org/material-ui/blob/master/examples/nextjs/pages/_document.js

It is something that we fix internally but how to configure correctly with NextJS.

@mnajdova mnajdova added package: system Specific to @mui/system support: question Community support but can be turned into an improvement and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 27, 2021
@daniielp
Copy link
Author

That fixed the issue. Thanks a lot, @siriwatknp :)

@ApayRus
Copy link

ApayRus commented May 7, 2022

@siriwatknp it doesn't work for me. I just copied everything from example: _app.js, document.js , I runed codemod to convert v4 JSS to MUI v5 styles.
But on first app load appears gigantic icons

@Shahzayb
Copy link

Getting the same issue. Then I tried setting style={{width: '1em', height: '1em'}} and it look somewhat ok, but still resizing. I think the styles aren't loading somehow. I'm using static build btw.

@btdtech
Copy link

btdtech commented May 25, 2022

Hi @siriwatknp I am experiencing the same issue.

I followed the repo provided by MUI (https://github.com/mui/material-ui/tree/HEAD/examples/nextjs-with-typescript).

The theme is applied in local dev but not when I deploy to production. (https://btdtech.io/)

As you can see from the website, when you first visit it there is no styling applied. If you use the link to navigate to the ABOUT page then you will see it styled. However if you refresh the ABOUT page, the styling disappears again.

This is the link to the repository for your perusal https://github.com/btdtech/company-website.

Look forward to your reply!

Bac

@btdtech
Copy link

btdtech commented May 29, 2022

Hi everyone,

I have been digging and it seems that Emotion cache's style component has to style. Do we know why this is? I really would like to get to the bottom of this, otherwise I might have to find another CSS solution.

Cheers,

Bac

@siriwatknp siriwatknp reopened this May 30, 2022
@siriwatknp
Copy link
Member

I can confirm that our official example does not work. I looking into this.

@siriwatknp siriwatknp added bug 🐛 Something doesn't work external dependency Blocked by external dependency, we can’t do anything about it and removed support: question Community support but can be turned into an improvement bug 🐛 Something doesn't work labels May 30, 2022
@siriwatknp
Copy link
Member

siriwatknp commented May 30, 2022

It seems like the problem comes from this:

// pages/_document.js
const initialProps = await Document.getInitialProps(ctx);
// console.log(initialProps.html) returns empty string
const emotionStyles = extractCriticalToChunks(initialProps.html);

The initialProps.html returns an empty string which is why emotion cannot create correct styles. When I downgrade react from latest(v18.0.0) to v17.0.2, it works. So I think it is something wrong with NextJS + React 18.

As a workaround, I suggest downgrading react to v17.0.2 for now and I will open an issue on the nextjs repo.

@siriwatknp
Copy link
Member

siriwatknp commented May 30, 2022

I can confirm that the issue comes from nextjs latest. I switch from latest to canary and it works. @btdtech @ApayRus @Shahzayb Can you try the canary version of nextjs?

-"next": "latest",
+"next": "canary",

Change the package json then run yarn and yarn build. It worked for me.

Note that the latest nextjs (v12.1.6) (that does not work) was published 28 days ago and I could not find the PR that fixed the issue. If anyone knows, feel free to link the issue and the PR.

I guess this PR vercel/next.js#36792 fixes the issue.

@btdtech
Copy link

btdtech commented May 30, 2022

I can confirm that the issue comes from nextjs latest. I switch from latest to canary and it works. @btdtech @ApayRus @Shahzayb Can you try the canary version of nextjs?

-"next": "latest",
+"next": "canary",

Change the package json then run yarn and yarn build. It worked for me.

Note that the latest nextjs (v12.1.6) (that does not work) was published 28 days ago.

Thank you so much @siriwatknp . It solved the issue!

I can understand that there is a bug in nextjs, but why was yarn important in all of this? I tried NPM but didn't work.

@siriwatknp
Copy link
Member

I can confirm that the issue comes from nextjs latest. I switch from latest to canary and it works. @btdtech @ApayRus @Shahzayb Can you try the canary version of nextjs?

-"next": "latest",
+"next": "canary",

Change the package json then run yarn and yarn build. It worked for me.
Note that the latest nextjs (v12.1.6) (that does not work) was published 28 days ago.

Thank you so much @siriwatknp . It solved the issue!

I can understand that there is a bug in nextjs, but why was yarn important in all of this? I tried NPM but didn't work.

Thanks, I am closing this issue then.

@ApayRus
Copy link

ApayRus commented May 30, 2022

@siriwatknp I downgraded MUI to 4 :-(

@Taliss
Copy link

Taliss commented Jun 7, 2022

@siriwatknp
One way to fix this (even though I am not sure if it's a fix or just a side-effect) is not to use emotionCache.
NextJS now support SSR with emotion. This is also working out with a simple _document file, without the need for enhancing and style injections.

next.config: ( flag emotion )

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  compiler: {
    emotion: true,
  },
}

module.exports = nextConfig

_document: ( no extra enhance code and injections )

import { Html, Head, Main, NextScript } from 'next/document'
import theme from 'theme'

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <meta name="theme-color" content={theme.palette.primary.main} />
        ...
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

_app: ( no cache provider )

export default function App({ Component, pageProps }: Props) {
  const getLayout = Component.getLayout || ((page) => page)

  return (
    // <CacheProvider value={emotionCache}>
    <ThemeProvider theme={theme}>
      {getLayout(<Component {...pageProps} />)}
    </ThemeProvider>
    // </CacheProvider>
  )
}

versions:

    "next": "^12.1.6",
    "@emotion/react": "^11.8.2",
    "@emotion/styled": "^11.8.1",
    "@mui/material": "^5.5.3",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",

@siriwatknp
Copy link
Member

@Taliss The difference is that the example uses the advanced approach, not the default approach.

@giorgiPapava
Copy link

I'm still facing this issue. nothing seems to work for me mentioned above.

ReBank this is the website, I can't give the source code since its enterprise application but I can tell you that I'm using Next.js, MUI, styled-components (not @mui/styled-engine-sc, regular mui configuration with just styled-components styled api). As you can see styles are flickering on the first load. I'm using Next.js SWC and have styled-components turned on in next.config.js and using this configuration. Does anyone have this problem and is there any fix to this?

@giorgiPapava
Copy link

I'm still facing this issue. nothing seems to work for me mentioned above.

ReBank this is the website, I can't give the source code since its enterprise application but I can tell you that I'm using Next.js, MUI, styled-components (not @mui/styled-engine-sc, regular mui configuration with just styled-components styled api). As you can see styles are flickering on the first load. I'm using Next.js SWC and have styled-components turned on in next.config.js and using this configuration. Does anyone have this problem and is there any fix to this?

I fixed it with adopting styled-engine-sc with yarn resolutions and next webpack resolve alias

@vascojm82
Copy link

I can confirm that the issue comes from nextjs latest. I switch from latest to canary and it works. @btdtech @ApayRus @Shahzayb Can you try the canary version of nextjs?

-"next": "latest",
+"next": "canary",

Change the package json then run yarn and yarn build. It worked for me.

Note that the latest nextjs (v12.1.6) (that does not work) was published 28 days ago and I could not find the PR that fixed the issue. If anyone knows, feel free to link the issue and the PR.

I guess this PR vercel/next.js#36792 fixes the issue.

Hi, I upgraded NextJS from v12.0.10 to v12.1.7-canary.39 and I'm still seeing this issue, the style from the theme won't load on the page's first render, anyone can help?

@daveteu
Copy link

daveteu commented Jul 2, 2022

"next": "^12.2.0", seems to have fixed the issue.

Working version as of today

       "next": "^12.2.0", 
        "@emotion/react": "^11.9.3",
        "@emotion/server": "^11.4.0",
        "@emotion/styled": "^11.9.3",

        "@mui/icons-material": "^5.8.4",
        "@mui/lab": "^5.0.0-alpha.88",
        "@mui/material": "^5.8.5",

@Homerlrh
Copy link

I can confirm that the issue comes from nextjs latest. I switch from latest to canary and it works. @btdtech @ApayRus @Shahzayb Can you try the canary version of nextjs?

-"next": "latest",
+"next": "canary",

Change the package json then run yarn and yarn build. It worked for me.

Note that the latest nextjs (v12.1.6) (that does not work) was published 28 days ago and I could not find the PR that fixed the issue. If anyone knows, feel free to link the issue and the PR.

I guess this PR vercel/next.js#36792 fixes the issue.

Still facing the same problem, style is not load on first load, I also followed the _document.js. What else am i missing ?

"react": "^17.0.2",
"next": "canary",

"@emotion/cache": "latest",
"@emotion/react": "latest",
"@emotion/server": "latest",
"@emotion/styled": "latest",

"@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.78",
"@mui/material": "^5.6.2",
"@mui/styles": "^5.6.2",
"@mui/system": "5.9.1",

@stevenkeith85
Copy link

stevenkeith85 commented Jul 28, 2022

Yup...

Just wasted some time with this one. In case this is anyone else's issue.

https://developer.chrome.com/blog/new-in-devtools-102/#network-preview

I used to be able to click on the dev tools preview tab, and see a nicely rendered page. At some point I've presumably upgraded Chrome (or its done it itself 🤷‍♂️) and things stopped working.

I probably never noticed at the time; so when I next clicked on the preview tab I got the whole 'plain html' with no CSS applied. (and assumed I'd broken something)

I've just turned JavaScript via dev tools and checked; and everything is properly rendering.

TLDR; things might actually be working / don't trust the chrome preview tab.

Edit: Not 100% sure CSP applies to inline stylesheets; but I can see the styles in the response so 🤷‍♂️

@kelvindecosta
Copy link

I followed @Taliss 's comment in this thread: #30410 (comment)

Works like a charm.
I'm using all the latest packages.

Is there a benefit to using the default approach that is missing with this configuration?
It just seems needlessly complicated.

@YauhenDavidovich
Copy link

Adding this to _document.js finally solved the problem
`MyDocument.getInitialProps = async (ctx) => {
const originalRenderPage = ctx.renderPage;
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);

const sheets = new ServerStyleSheets();

ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) =>
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,
};
};`

@roux1max
Copy link

roux1max commented Oct 5, 2022

It seems the example repo is now working. I just changed my _app.ts and _document.ts and everything seems to work fine both in local dev and in staging env (wth next build).

I am testing on Brave Browser (which is just a layer on top of Chrome) version 1.43.93 (with Chromium: 105.0.5195.127) and with the following env:

System:
  OS: Linux 5.15 Ubuntu 20.04.5 LTS (Focal Fossa)
Binaries:
  Node: 18.9.0
  npm: 8.19.1
Browsers:
  Chrome: 105.0.5195.125
npmPackages:
  @emotion/react: 11.10.x => 11.10.4 
  @emotion/styled: 11.10.x => 11.10.4 
  @mui/base:  5.0.0-alpha.98 
  @mui/core-downloads-tracker:  5.10.6 
  @mui/icons-material: 5.10.6 => 5.10.6 
  @mui/material: 5.10.6 => 5.10.6 
  @mui/private-theming:  5.10.6 
  @mui/styled-engine:  5.10.6 
  @mui/system:  5.10.6 
  @mui/types:  7.2.0 
  @mui/utils:  5.10.6 
  @types/react: 18.0.20 => 18.0.20 
  react: 18.2.0 => 18.2.0 
  react-dom: 18.2.0 => 18.2.0 
  typescript: 4.8.3 => 4.8.3

@vascojm82
Copy link

vascojm82 commented Dec 6, 2022

"next": "^12.2.0", seems to have fixed the issue.

Working version as of today

       "next": "^12.2.0", 
        "@emotion/react": "^11.9.3",
        "@emotion/server": "^11.4.0",
        "@emotion/styled": "^11.9.3",

        "@mui/icons-material": "^5.8.4",
        "@mui/lab": "^5.0.0-alpha.88",
        "@mui/material": "^5.8.5",

I did what daveteu posted above and I still see the same issue happening but not as often. I have:
"next": "^12.2.0",
"@mui/lab": "^5.0.0-alpha.88",
"@mui/material": "^5.8.5",
"@mui/styles": "^5.4.1",
"@emotion/react": "^11.9.3",
"@emotion/server": "^11.4.0",
"@emotion/styled": "^11.9.3",

Can anyone help please?

@rahulcn
Copy link

rahulcn commented Feb 7, 2023

@hamza172
Copy link

hamza172 commented Apr 26, 2023

Hey
I had come across the same issue.
I have tried all the things suggested above but nothing has worked.
Oh and my issue isnt only for first time, it never works
https://myfreecourse-front-v2-r0rfrryqq-hamza172.vercel.app

Using @mui v5
Next.js 13
with Typescript

my _document file is
`import React from 'react';
import Document, { Html, Head, Main, NextScript, DocumentContext } from 'next/document';
import { ServerStyleSheets } from '@mui/styles';

export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}

render() {
return (







);
}
}

// getInitialProps belongs to _document (instead of _app),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render

// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;

ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});

const initialProps = await Document.getInitialProps(ctx);

return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
`

my_app file is
`import '@/styles/globals.css'
import '@/styles/universal.css'
import '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import ScopedCssBaseline from '@mui/material/ScopedCssBaseline';
import type { AppProps } from 'next/app'

export default function App({ Component,pageProps }: AppProps) {
return (
<>


<Component {...pageProps} />

</>
);
}

`

@saadkhan6670
Copy link

I followed @Taliss 's comment in this thread: #30410 (comment)

Works like a charm.
I'm using all the latest packages.

@kaiquevalentim
Copy link

I had a similar problem but i worked around it probably with not the best solution. In my case i was making a project using react and django, this project had a google verification to login and after this it load the home page. In the first load only the buttons itens from material ui package were without the styled, but after you refresh the page the style works again. So i created a context to use a variable that apoint this first load and automatically refresh the page. Like i said, this is not the best way but worked for me.
I hope someone with it.

@kukadiyaAni
Copy link

kukadiyaAni commented Sep 21, 2023

"next": "^13.5.2",
"react": "^18.2.0",

"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.45",
"@material-ui/styles": "^4.11.5",

I have the above configuration work fine but get this issue after updating with the latest version 13.5.2,

@hamza172 I tried your solution but now work in above version

Thanks in advance if anyone can help with this

@famdude
Copy link

famdude commented Mar 7, 2024

so what is the right solution now in 2024?

@famdude
Copy link

famdude commented Apr 4, 2024

so what is the right solution now in 2024?

@siriwatknp I think it's an important issue. and now after more than 2 years, even with the new versions of Next js, MUI and Emotion, the problem still exists. can you look around please?

@famdude
Copy link

famdude commented Apr 4, 2024

I can confirm that not using CacheProvider, this problem is fixed. But as my app is RTL so I HAVE to use it.
here's _app.js file:

import * as React from "react";
import Head from "next/head";
import { ThemeProvider } from "@mui/material/styles";
import rtlPlugin from "stylis-plugin-rtl";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import { prefixer } from "stylis";
import theme from "../src/theme";


// Create rtl cache
const cacheRtl = createCache({
  key: "muirtl",
  stylisPlugins: [prefixer, rtlPlugin],
});

function MyApp({ Component, pageProps }) {
return (
    <CacheProvider value={cacheRtl}>
      <ThemeProvider theme={theme}>
        <Head>
        // header tags here
        </Head>
        <Component {...pageProps} />
      </ThemeProvider>
    </CacheProvider>
  );
}

export default MyApp;

commenting <CacheProvider value={cacheRtl}></CacheProvider> out fixes problem, but makes the app look crushed as it changes to LTR.

@hadarhubara10
Copy link

#30410 (comment)
@famdude
I have the same issue. Have you come up with a solution?

@leonardo015
Copy link

leonardo015 commented Aug 9, 2024

My solution used suppressHydrationWarning and solved other details.

It works this way:

  • If user have not set a preference on the app (localStorage) i get it from his system preference.
    • While theres no stored preference if user changes his system preferences the app then gets updated to that instantly.
  • If user has a stored preference then it takes precedence over system's.
  • I also solved the issue on initial load in which the app rendered a blank screen or either the wrong theme before the theme could get it set by returning a loading screen.

Ps: Im using Next.js v14 and Material UI v5.16

(simplified code)

Root Layout:

import { CustomThemeProvider } from "@/context/CustomThemeContext";
import React from "react";
import "./globals.css";

// trick to avoid SSR mismatch due to html inline colorMode script
const mockSSRColorMode = () => "light";

export default function RootLayout({
	children,
}: {
	children: React.ReactNode;
}) {
	return (
		<html
			lang="en"
			style={{ colorScheme: mockSSRColorMode() }}
			suppressHydrationWarning
		>
			<head>
				{/* Inline script to set color scheme on the first load (to avoid wrong color loading screen) */}
				<script
					dangerouslySetInnerHTML={{
						__html: `
                        (function() {
                            const storedColorMode = localStorage.getItem('colorMode');
                            const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
                            const colorMode = storedColorMode || (prefersDarkMode ? 'dark' : 'light');
                            document.documentElement.style.colorScheme = colorMode;
                        })();
                    `,
					}}
				/>
			</head>
			<body>
				<CustomThemeProvider>{children}</CustomThemeProvider>
			</body>
		</html>
	);
}

CustomThemeContext:

"use client";
import Loading from "@/app/loading";
import { PaletteMode, useMediaQuery } from "@mui/material";
import {
	Theme,
	ThemeProvider
} from "@mui/material/styles";
import React, {
	createContext,
	ReactNode,
	useContext,
	useEffect,
	useMemo,
	useState,
} from "react";

interface ThemeContextType {
	colorMode: PaletteMode;
	toggleColorMode: () => void;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

interface CustomThemeProviderProps {
	children: ReactNode;
}

export const CustomThemeProvider: React.FC<CustomThemeProviderProps> = ({
	children,
}) => {
	const [colorMode, setColorMode] = useState<PaletteMode>("light");
	const [loading, setLoading] = useState(true);
	const sysPreferDark = useMediaQuery("(prefers-color-scheme: dark)", {
		noSsr: true,
	});

	// This prop determines native elements theme
	const setColorSchemeOnHtml = (newMode: PaletteMode) =>
		document.documentElement.style.setProperty("color-scheme", newMode);

	// First-load color-mode routine: use stored OR system-preference OR fallback to 'light'
	// Set it on state+themecontext AND on <html>'s color-scheme style prop
	useEffect(() => {
		const storedColorMode = localStorage.getItem("colorMode") as PaletteMode;
		const newMode = storedColorMode || (sysPreferDark ? "dark" : "light");
		setColorMode(newMode);
		setColorSchemeOnHtml(newMode);
		setLoading(false);
	}, [sysPreferDark]);

	const theme: Theme = useMemo(() => {
		// ... mui createStyles()
	}, [colorMode]);

	// User-triggered color-mode change: set preference on storage and html
	const toggleColorMode = () => {
		setColorMode((prevMode) => {
			const newMode = prevMode === "light" ? "dark" : "light";
			localStorage.setItem("colorMode", newMode);
			setColorSchemeOnHtml(newMode);
			return newMode;
		});
	};

	// on first-load the loading screen is immediatelly displayed
	// until the theme is loaded with the uptodate color-mode
	if (loading) {
		return <Loading />;
	}

	return (
		<ThemeContext.Provider value={{ colorMode, toggleColorMode }}>
			<ThemeProvider theme={theme}>{children}</ThemeProvider>
		</ThemeContext.Provider>
	);
};

export const useCustomThemeContext = (): ThemeContextType => {
	const context = useContext(ThemeContext);
	if (!context) {
		throw new Error("useCustomTheme must be used within a CustomThemeProvider");
	}
	return context;
};

And no color-scheme related styles on any CSS file.

@medeirosjoaquim
Copy link

still happening on Next 14.0.4 ,
this problem was marked as solved in vercel/next.js#15642
but it is still persisting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
examples Relating to /examples external dependency Blocked by external dependency, we can’t do anything about it package: system Specific to @mui/system
Projects
None yet
Development

No branches or pull requests