Material UI 6 CssVarsProvider causes Suspense to reload async components
Steps to reproduce
Link to live example: https://next-15-mui-6-suspense-flicker.vercel.app/
Steps:
- Open the link
- Refresh the page
- See Suspense boundary to re-render async loaded component
https://github.com/user-attachments/assets/ef7ba60e-3888-4010-b0b0-527c2a3567d1
This behaviour is a regression – using Material 5.16.7 causes Suspense to work as expected:
https://github.com/user-attachments/assets/0aea80ab-b7eb-4893-90cc-6cd12fda7fc0
Link to repo with Material 6 reproduction: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker
Link to branch with working Material 5 example: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker/tree/material-5
Current behavior
On first render, async components inside Suspense boundary are reloaded and re-rendered
Expected behavior
Should work like in Material 5 – async component tree should not be re-mounted on first render
Context
I am working on a https://ensite.in, which is a no-code website builder. Due to large amount of building-blocks user can choose from, the whole app renders as an async-component tree
Your environment
npx @mui/envinfo
System:
OS: macOS 14.2.1
Binaries:
Node: 20.12.0 - ~/.nvm/versions/node/v20.12.0/bin/node
npm: 10.5.0 - ~/.nvm/versions/node/v20.12.0/bin/npm
pnpm: Not Found
Browsers:
Chrome: 127.0.6533.100
Edge: Not Found
Safari: 17.2.1
npmPackages:
@emotion/react: ^11.13.0 => 11.13.0
@emotion/styled: ^11.13.0 => 11.13.0
@mui/core-downloads-tracker: 6.0.0-dev.240424162023-9968b4889d
@mui/material: ^6.0.0-beta.5 => 6.0.0-beta.5
@mui/material-nextjs: ^6.0.0-beta.4 => 6.0.0-beta.4
@mui/private-theming: 6.0.0-beta.5
@mui/styled-engine: 6.0.0-beta.5
@mui/system: 6.0.0-beta.5
@mui/types: 7.2.15
@mui/utils: 6.0.0-beta.5
@types/react: ^18 => 18.3.3
react: 19.0.0-rc-f994737d14-20240522 => 19.0.0-rc-f994737d14-20240522
react-dom: 19.0.0-rc-f994737d14-20240522 => 19.0.0-rc-f994737d14-20240522
typescript: ^5 => 5.5.4
Search keywords: material 6 suspense css vars cssvarsprovider
@awinogrodzki in v6, the CssVarsProvider contains a rerender (not a remount) after hydration so that the mode is updated on the client. It's strange that a rerender will cause a Suspense to display a fallback. Is this the expected behavior?
Good point @siriwatknp. I think that the remount comes from a root async component after mode re-render in CssVarsProvider. Let me run some more experiments to be sure and I'll get back to you
@siriwatknp, after running different experiments I can confirm that no remount happens. I think I must've observed it when isolated the case in the real app. I don't think it's related to this issue however, so let's just ignore it.
I still think the issue lies somewhere inside CssVarsProvider. Here's some experiments that I've performed:
Recordings of the production build
Material UI 6
Code for layout: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker/blob/main/app/layout.tsx
You can notice that it's basic layout created using create-next-app updated with InitColorSchemeScript, CssVarsProvider and AppRouterCacheProvider, according to the docs
Code for theme: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker/blob/main/app/theme.ts
It's just a basic theme with custom selector
Light mode
https://github.com/user-attachments/assets/71410df2-f3e1-453d-820a-5142ab2850e2
Dark mode
https://github.com/user-attachments/assets/e0e5877e-923b-4d8f-933a-6ea352a680a8
Material UI 5
Code for layout: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker/blob/material-5/app/layout.tsx Code for theme: https://github.com/awinogrodzki/next-15-mui-6-suspense-flicker/blob/material-5/app/theme.ts
Light mode
https://github.com/user-attachments/assets/420a7832-ab08-4d9f-ac45-cd6b65946a1b
Dark mode
https://github.com/user-attachments/assets/c10a0561-f349-4057-88de-7f07fecd66b6
Control
I also tested the behavior with MUI6, but without CssVarProvider in layout.tsx:
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
<AppRouterCacheProvider>
<InitColorSchemeScript attribute="[data-scheme-%s]" />
{children}
</AppRouterCacheProvider>
</body>
</html>
);
}
It also does work as expected, which points that the problem is somewhere inside CssVarsProvider
Light mode
https://github.com/user-attachments/assets/c9174e33-a86e-4195-8b93-1530ab2d4744
Dark mode
https://github.com/user-attachments/assets/46910d50-441e-4a58-a0ef-e2c2a929445c
Hey @siriwatknp,
Are there any updates on the issue?
I have updated Material UI to the latest version – 6.0.2, and the issue still exists.
I have also replaced CssVarsProvider and extendTheme with recommended ThemeProvider + createTheme – the issue is still reproducible
Is there anything I could do to help?
I've cloned material-ui repository to debug the issue and it seems that everything starts working properly when I comment this line:
https://github.com/mui/material-ui/blob/master/packages/mui-system/src/cssVars/useCurrentColorScheme.ts#L163
Is this state update necessary?
With this line commented system, light and dark mode seems to be working correctly and Suspense also works as expected.
Maybe you could at least provide a opt-out from this behaviour?
Maybe you could at least provide a opt-out from this behaviour?
That'd be possible.
@awinogrodzki I created a PR to add disableClientRerender to ThemeProvider. Tested with your repo, it works. Please try:
"@mui/material": "https://pkg.csb.dev/mui/material-ui/commit/2b33a223/@mui/material",
@siriwatknp awesome! I just tested and it works as expected. Thank you!
@siriwatknp maybe it's also related https://github.com/mui/material-ui/issues/43263
I just tried with disableClientRerender and "@mui/material": "https://pkg.csb.dev/mui/material-ui/commit/2b33a223/@mui/material",
And it works as expected. No more flickering
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.
[!NOTE] @awinogrodzki How did we do? Your experience with our support team matters to us. If you have a moment, please share your thoughts in this short Support Satisfaction survey.