Material-ui 样式在使用 useMediaQuery 挂钩切换 light/dark 主题时被覆盖

Material-ui style getting overwritten when switching light/dark theme using useMediaQuery hook

我正在使用 next.js 和 material-ui,并根据用户偏好更改主题。 但是似乎当切换到灯光模式时,我设置的样式(使用 JSS)将被覆盖,只有在使用灯光模式时才会发生这种情况我什至试图反转两个主题,但它不起作用。经过大量尝试后,我发现当更改 system/browser 以使用不同于 useMediaQuery() 挂钩中设置的主题时,问题就会发生。 const isInDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); (比如set prefers-color-scheme to dark, light theme会导致Styles被覆盖。)但是我还是不知道为什么会这样,如何避免。

编辑:手动设置 isInDarkMode = false 后,无论模式如何,样式都会被覆盖..所以可能 useMediaQuery 没有导致问题但实际上有点解决问题..?

编辑我尝试将此应用程序部署到vercel后,主页在所有颜色模式下都完全正常,通过getStaticPaths()生成的部分页面仍然存在问题。

这在 iOS 上的 Safari 和 Windows 上的 Chrome 上都进行了测试,所有问题都出现了。

我用来设置主题的代码(我在_app.js中设置):

import Header from "../components/Header";
import React from "react";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import "../styles/global.css";

function MyApp({ Component, pageProps }) {
  const isInDarkMode = useMediaQuery("(prefers-color-scheme: dark)");

  const theme = React.useMemo(
    () =>
      createTheme({
        spacing: 8,

        palette: {
          type: isInDarkMode ? "dark" : "light",
          primary: {
            main: isInDarkMode ? "#8A6BBE" : "#6F3381",
          },
          secondary: {
            main: "#CB4042",
          },
          background: {
            default: isInDarkMode ? "#1c1c1c" : "#fffffb",
          },
        },

        typography: {
          h3: {
            fontFamily: "Source Serif Pro, serif",
            fontWeight: "600",
            fontSize: "2.2rem",
            "@media (min-width:600px)": {
              fontSize: "3rem",
            },
          },
        },
      }),
    [isInDarkMode]
  );

  return (
    <>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <Header isInDarkMode={isInDarkMode} />
        <Component {...pageProps} />
      </ThemeProvider>
    </>
  );
}

export default MyApp;

(试过不用useMemo,但没有解决问题。)

const useStyles = makeStyles({
  root: {
    maxWidth: 345,
    backgroundColor: "rgba(255, 255, 255, 0)",
    border: "1px solid rgba(138, 107, 190, 0.7)",
    borderRadius: "8px",
  },
});

(Style的一个例子,该问题会导致所有样式被覆盖,包括maxWidth、BackgroundColor和border/borderRadius)

问题解决了!它似乎是由于没有删除服务器端注入 CSS 引起的。我按照教程 Here

供参考,这些是我的 _document.js

import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@material-ui/core/styles";

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head></Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `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(),
    ],
  };
};

和_app.js

import Header from "../components/Header";
import React from "react";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";

import { lightTheme, darkTheme } from "../utils/themes/Theme";
import "../styles/global.css";

function MyApp({ Component, pageProps }) {
  const isInDarkMode = useMediaQuery("(prefers-color-scheme: dark)");

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

  return (
    <ThemeProvider theme={isInDarkMode ? darkTheme : lightTheme}>
      <CssBaseline />
      <Header isInDarkMode={isInDarkMode} />
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;

(我改为在不同的文件中创建主题,但它应该是可选的)