You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Next.js 13中暗黑主题闪烁问题

主题切换闪烁问题:Next.js站点初始加载先显示浅色再切深色

我有一个基于Next.js、Typescript、MUI、TinaCMS和Redux的站点,支持深色与浅色主题,主题状态存储在localStorage中并通过Redux管理,默认主题为深色。目前遇到的问题是:进入页面时会先显示约0.5秒的浅色主题,之后才切换为深色主题。

我已配置自定义文档/pages/_document.tsx,在其中引入了/scripts/theme.js脚本和ThemeProvider,相关代码如下:

theme.js 代码

// Code duplicate to prevent the following error:
// https://github.com/vercel/next.js/discussions/12533

(() => {
  const defaultTheme = "dark";

  const getStorageTheme = () => {
    return localStorage.theme;
  };

  const getBrowserTheme = () => {
    if (window.matchMedia === undefined) {
      return undefined;
    }

    if (window.matchMedia("(prefers-color-scheme: light)").matches) {
      return "light";
    } else {
      return "dark";
    }
  };

  const getInitialTheme = () =>
    getStorageTheme() || getBrowserTheme() || defaultTheme;

  const theme = getInitialTheme();

  localStorage.setItem("theme", theme);

  const body = document.querySelector("body");

  if (theme === "dark") {
    body?.classList.add("dark-theme");
  } else {
    body?.classList.remove("dark-theme");
  }
})();

_document.tsx 代码

/* eslint-disable @next/next/no-sync-scripts */
import { Head, Html, Main, NextScript } from "next/document";
import Script from "next/script";

const Document = () => (
  <Html lang="en">
    <Head>
      <Script src="/scripts/theme.js" strategy="beforeInteractive" />
    </Head>
    <body>
      <Main />
      <NextScript />
    </body>
  </Html>
);

export default Document;

/components/MUI/ThemeProvider.tsx 代码

import { PaletteMode, ThemeProvider as MUIThemeProvider } from "@mui/material";
import { defaultTheme, setTheme, Theme } from "redux/slices/theme";
import { useAppDispatch, useAppSelector } from "redux/typesHooks";

import useIsomorphicLayoutEffect from "../useIsomorphicLayoutEffect";
import getMUITheme from "./getMUITheme";

interface Props {
  children: JSX.Element;
}

const getStorageTheme = (): Theme | undefined => {
  return localStorage.theme;
};

const getBrowserTheme = (): Theme | undefined => {
  if (window.matchMedia === undefined) {
    return undefined;
  }

  if (window.matchMedia("(prefers-color-scheme: light)").matches) {
    return "light";
  } else {
    return "dark";
  }
};

const getInitialTheme = (): Theme =>
  getStorageTheme() || getBrowserTheme() || defaultTheme;

const ThemeProvider = ({ children }: Props) => {
  const dispatch = useAppDispatch();
  const theme = useAppSelector((state) => state.theme);
  const MUITheme = getMUITheme(theme as PaletteMode);

  useIsomorphicLayoutEffect(() => {
    const initialTheme = getInitialTheme();

    dispatch(setTheme(initialTheme));
  }, [dispatch]);

  return <MUIThemeProvider theme={MUITheme}>{children}</MUIThemeProvider>;
};

export default ThemeProvider;

我曾尝试过相关方案,但完全没有效果。

内容的提问来源于stack exchange,提问作者Winheart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:54:53