怎么解决?)
Material UI 的 SSR 应用出现暗色模式闪烁dark mode flicker怎么解决【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Googles Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui在用 Next.js 等框架做服务端渲染SSR的 Material UI 应用里开启暗色模式后常见一个问题把应用切到 dark mode 后刷新页面页面会先短暂显示亮色主题等应用完全加载后才切回暗色。这个闪一下就是 dark mode flicker。Material UI 官方文档对成因的解释是SSR 内容在到达用户设备之前就在服务端生成Material UI 无法在服务器上检测到用户选择的颜色模式于是客户端水合hydration阶段从 light 切到 dark屏幕上就能看到这次跳变。修复路径来自 Dark mode 文档、InitColorSchemeScript 组件文档 和 CSS 主题变量配置文档启用 CSS 主题变量、清除代码里的theme.palette.mode dark判断再通过InitColorSchemeScript组件让正确的颜色模式在首次渲染时就生效。先确认你的应用属于哪种情况不是所有开了暗色模式的 SSR 应用都需要动InitColorSchemeScript先对照 CSS 主题变量用法文档 的说明区分两种情况应用只跟随系统的prefers-color-scheme媒体查询用户不能手动切换启用 CSS 主题变量即可这种默认方式在服务端渲染下不需要额外配置就能工作闪烁随之消失。应用支持用户手动在 light / dark 之间切换主题里设置了colorSchemeSelector代码里用useColorScheme切换必须用 CSS 变量 InitColorSchemeScript组件的组合来避免闪烁。下面以第二种情况为主路径展开框架示例为 Next.jsApp Router 和 Pages RouterGatsby 作为可选分支。第一步主题启用 CSS 主题变量与暗色 color scheme按 CSS 主题变量配置文档 的Toggling dark mode manually一节主题里同时开启colorSchemes和cssVariablesimport { ThemeProvider, createTheme } from mui/material/styles; const theme createTheme({ colorSchemes: { light: true, dark: true, }, cssVariables: { colorSchemeSelector: class, }, }); function App() { return ThemeProvider theme{theme}{/* Your app */}/ThemeProvider; }colorSchemeSelector决定生成的 CSS 选择器形式有三种取值class往html上添加 class生成.light { ... }/.dark { ... }。data往html上添加 data 属性生成[data-light] { ... }/[data-dark] { ... }。自定义字符串class 选择器必须以.开头data 属性选择器必须以[开头例如.theme-%s生成.theme-light/.theme-dark。注意这个值要和后面InitColorSchemeScript的attributeprop 保持一致见第三步。如果应用不做手动切换这里只需要cssVariables: true。第二步清除代码中的theme.palette.mode dark判断官方文档明确要求为了防止闪烁需要确保代码库中不存在对theme.palette.mode dark的用法CSS 主题变量用法文档 也单独用 warning 提示用theme.palette.mode切换亮暗样式会产生 unwanted flickering effect。存在这类条件判断时改用theme.applyStyles()函数。configuration 文档给出的 Card 示例如下import Card from mui/material/Card; function App() { return ( Card - sx{(theme) ({ - backgroundColor: theme.palette.mode dark ? #000 : #fff, - :hover: { - backgroundColor: theme.palette.mode dark ? #333 : #f5f5f5, - }, - })} sx{[ { backgroundColor: #fff, :hover: { backgroundColor: #f5f5f5, }, }, (theme) theme.applyStyles(dark, { backgroundColor: #000, :hover: { backgroundColor: #333, }, }), ]} / ); }第三步添加 InitColorSchemeScript 组件InitColorSchemeScript的作用是在 React 运行之前执行根据用户偏好往颜色方案节点默认是html元素上写入 class 或属性让首次渲染就直接应用正确的颜色模式。文档要求把它渲染为body标签的第一个子元素且attribute的值必须与主题里的colorSchemeSelector相同。Next.js App Router放在根layout文件里示例对应 InitColorSchemeScript 文档 与 CSS 主题变量配置文档 的写法import InitColorSchemeScript from mui/material/InitColorSchemeScript; export default function RootLayout(props) { return ( html langen suppressHydrationWarning body {/* 必须位于 main 元素之前 */} InitColorSchemeScript attributeclass / main{props.children}/main /body /html ); }这里html上的suppressHydrationWarning是必做的文档警告如果不加因为InitColorSchemeScript会更新html元素你会看到Extra attributes from the server的 warning。Next.js Pages Router放在自定义pages/_document文件中import Document, { Html, Head, Main, NextScript } from next/document; import InitColorSchemeScript from mui/material/InitColorSchemeScript; export default class MyDocument extends Document { render() { return ( Html Head.../Head body {/* 必须位于 Main 元素之前 */} InitColorSchemeScript attributeclass / Main / NextScript / /body /Html ); } }Gatsby可选分支Gatsby 项目把脚本放到gatsby-ssr.jsimport * as React from react; import InitColorSchemeScript from mui/material/InitColorSchemeScript; export function onRenderBody({ setPreBodyComponents }) { setPreBodyComponents([InitColorSchemeScript attributeclass /]); }attribute 的取值规则attribute与colorSchemeSelector一致的基础上还支持用%s占位符指定任意属性InitColorSchemeScript attribute[data-theme%s] / // html>InitColorSchemeScript defaultModedark /ThemeProvider theme{theme} defaultModedark文档说明defaultMode的取值可以是light、dark、system。验证修复是否生效检查html元素脚本在 React 之前运行用户偏好为 dark 且选择器为class时首屏 HTML 上应已带有html classdarkdata选择器则对应有[data-dark]。按 dark-mode 文档建议的测试方式在浏览器 DevTools 中把 CSS media featureprefers-color-scheme模拟为dark把应用切到 dark mode 后刷新页面页面应直接以暗色呈现不再出现亮色闪烁。检查控制台加上suppressHydrationWarning后不应再出现Extra attributes from the serverwarning如果仍出现说明html标签上漏了这个属性。使用useColorScheme做切换时要注意mode在首次渲染时总是undefined文档提示必须处理这种情况例如先返回 null否则会碰到 hydration mismatch 错误。React 水合树之后mode会被设为system以跟随用户偏好需要判断系统实际是亮色还是暗色时可以用systemMode属性当mode不是system时systemMode为undefined。相关限制如果你给ThemeProvider传过自定义storageManager同时又在用InitColorSchemeScript防 SSR 闪烁文档警告自定义 storage manager 必须包含localStorage的实现。只跟随系统prefers-color-scheme、不做手动切换的应用不需要InitColorSchemeScript——CSS 变量本身已解决闪烁此时不要画蛇添足地引入自定义选择器。Next.js 项目的完整集成AppRouterCacheProvider、documentGetInitialProps等见 Next.js 集成文档其中CSS theme variables一节同样指向本节的防闪烁方案。相关文档Dark mode闪烁问题现象描述、colorSchemes内置支持、storage manager 限制InitColorSchemeScript 组件组件用法、App Router / Pages Router 放置位置、attribute 自定义CSS 主题变量 - 配置Preventing SSR flickering 一节colorSchemeSelector各取值对应的 CSS 结果CSS 主题变量 - 用法cssVariables: true的默认行为与theme.palette.mode禁用提示【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Googles Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考