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

Next.js 13 搭配 MUI 刷新页面时主题样式失效问题求助

Next.js 13 搭配 MUI 刷新页面时主题样式失效问题求助

各位大佬好,我现在遇到一个头疼的问题,想请大家帮忙看看:

我用 Next.js 13 搭配 MUI 作为UI库,项目是RTL(右到左)布局,同时用到了自定义主题、React Query、Jalali日期本地化这些Provider。首次启动项目或者通过Next.js路由跳转时,页面样式都正常,但只要刷新浏览器页面,或者修改代码触发热更新后,样式就完全乱了!

下面是我的相关代码:

Root Layout(app/layout.tsx)

"use client";

import "./globals.css";

import shabnam from "@/utils/shabnam";

import ReactQueryProvider from "@/providers/ReactQueryProvider";

import RTLCacheProvider from "@/providers/RTLCacheProvider";

import CustomThemeProvider from "@/providers/CustomThemeProvider";

import JalaliLocalizationProvider from "@/providers/JalaliLocalizationProvider";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="fa" dir="rtl" className={shabnam.className}>
      <CustomThemeProvider>
        <ReactQueryProvider>
          <RTLCacheProvider>
            <JalaliLocalizationProvider>
              <body>{children}</body>
            </JalaliLocalizationProvider>
          </RTLCacheProvider>
        </ReactQueryProvider>
      </CustomThemeProvider>
    </html>
  );
}

CustomThemeProvider

import React, { useEffect, useMemo, useState } from "react";
import ThemeProvider from "@mui/material/styles/ThemeProvider";
import ThemeOptions from "@/theme";
import { createTheme } from "@mui/material/styles";

function CustomThemeProvider({ children }: { children: React.ReactNode }) {
  const theme = useMemo(() => createTheme(ThemeOptions), []);
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}

export default CustomThemeProvider;

ThemeOptions 配置

import { grey } from "@mui/material/colors";
import { PaletteOptions, ThemeOptions } from "@mui/material/styles";

const paletteColors: PaletteOptions = {
  mode: "light",
  primary: {
    main: "#1F71BD",
    dark: "#030B13",
  },
  secondary: {
    main: "#FCA311",
  },
  success: {
    main: "#36B368",
  },
  warning: {
    main: "#FCA311",
  },
  error: {
    main: "#FF7473",
  },
};

const ThemeOptions: ThemeOptions = {
  direction: "rtl",
  palette: paletteColors,
  typography: {
    fontFamily: "var(--font-shabnam)",
    fontSize: 14,
    fontWeightLight: 300,
    fontWeightRegular: 400,
    fontWeightMedium: 500,
  },
  components: {
    MuiSwitch: {
      styleOverrides: {
        root: {
          width: 46,
          height: 26,
          padding: 0,
        },
        thumb: {
          boxSizing: "border-box",
          width: 22,
          height: 22,
          color: "#fff",
        },
        track: {
          borderRadius: 13,
          backgroundColor: "#E9E9EA",
          opacity: 1,
          transition: "background-color 300ms",
          ".Mui-checked.Mui-checked + &": {
            opacity: 1,
          },
        },
        switchBase: {
          padding: 0,
          margin: "2px",
          transitionDuration: "300ms",
        },
      },
    },
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: "15px",
          boxShadow: "0px 0px 15px rgba(35, 35, 35, 0.1)",
          padding: "15px",
        },
      },
    },
    MuiLink: {
      styleOverrides: {
        root: {
          textDecoration: "none",
        },
      },
    },
    MuiPagination: {
      styleOverrides: {
        root: ({ theme }) => ({
          direction: "ltr",
          marginTop: "10px",
          "& .Mui-selected": {
            color: "white !important",
            backgroundColor: theme.palette.secondary.main + " !important",
          },
        }),
        ul: {
          justifyContent: "center",
          "& .MuiPaginationItem-root": {
            borderRadius: "12px",
            background: grey[200],
            border: "0px",
          },
        },
      },
    },
    MuiOutlinedInput: {
      styleOverrides: {
        root: {
          "& fieldset": {
            borderRadius: "15px",
            "& legend": {
              display: "none",
            },
          },
        },
      },
    },
    MuiInputLabel: {
      defaultProps: {
        shrink: true,
      },
    },
    MuiTextField: {
      styleOverrides: {
        root: (props) => ({
          marginTop: props.ownerState.label ? "40px" : "0px",
          "& .MuiFormLabel-root": {
            top: "-20px",
            fontSize: "22px",
          },
          "& .MuiFormLabel-shrink": {
            shrink: true,
          },
          "& .MuiOutlinedInput-notchedOutline": {
            top: "2px",
          },
          shrink: true,
        }),
      },
    },
  },
};

export default ThemeOptions;

问题具体表现:

  • 首次启动npm run dev后,页面样式完全正常
  • 刷新浏览器页面后,样式错乱(比如输入框、按钮的样式都不对了)
  • 通过Next.js路由跳转页面再返回,样式又恢复正常
  • 修改代码触发热更新后,样式也会错乱

我已经尝试过把useMemo改成useState来创建主题,但没有效果。有没有大佬遇到过类似问题?或者有什么排查方向可以给我指点一下?

万分感谢!

备注:内容来源于stack exchange,提问作者Ali Hosseini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 10:29:37