reactjs Prop“className”与服务器和客户端不匹配

zc0qhyus  于 2023-08-04  发布在  React
关注(0)|答案(2)|浏览(223)

我遵循了很多解决方案,比如这个https://stackoverflow.com/a/71081567/19460332和这个https://github.com/mui/material-ui/blob/master/examples/nextjs的官方解决方案,但没有一个对我有效。我正在使用NextJS,Material UI和JS-Cookies
我面临的问题是MUI交换机
看看我的代码https://github.com/MaheshYadavGitHub/pizza-gallery
下面是正在中断的部分的代码:
下面是Layout.js,其中切换到darkMode的开关未按预期工作。darkTheme从cookie中得到应用,但开关按钮在第一次渲染时仍然保持在关闭位置,但在另一次渲染后,它可以完美地工作,当再次手动刷新时,它会执行相同的行为:

import { useState, useContext } from "react";
import {
  Container,
  AppBar,
  Toolbar,
  Typography,
  Link,
  Switch,
  CssBaseline,
  ThemeProvider,
  createTheme,
} from "@material-ui/core";
import { red } from "@material-ui/core/colors";
import Head from "next/head";
import Image from "next/image";
import NextLink from "next/link";
import useStyles from "../utils/styles";
import { Store } from "../utils/Store";
import Cookies from "js-cookie";

const Layout = ({ title, children }) => {
  const { state, dispatch } = useContext(Store);
  const { darkMode } = state;
  const classes = useStyles();

  const theme = createTheme({
    palette: {
      type: darkMode ? "dark" : "light",
      primary: {
        main: "#556cd6",
      },
      secondary: {
        main: "#19857b",
      },
      error: {
        main: red.A400,
      },
    },
    typography: {
      fontFamily: ["Arial", "Roboto Condensed"].join(","),
      fontWeight: 700,
      h1: {
        fontSize: "1.6rem",
        margin: "1rem 0rem",
        fontWeight: 600,
        "@media (min-width:600px)": {
          fontSize: "2.6rem",
        },
      },
      h6: {
        fontWeight: 700,
      },
      navLinks: {
        color: "#fff",
      },
    },
  });

  const handleThemeChange = (event) => {
    dispatch({ type: darkMode ? "DARK_MODE_OFF" : "DARK_MODE_ON" });
    const newThemeMode = !darkMode;
    Cookies.set("darkMode", newThemeMode ? "ON" : "OFF");
  };
  return (
    <>
      <Head>
        <title>{title ? `${title} - Pizza Gallery` : "Pizza Gallery"}</title>
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />

        <AppBar position="static" className={classes.navbar}>
          <Toolbar>
            <NextLink href="/" passHref>
              <Link>
                <Typography
                  variant="h6"
                  className={classes.brand}
                  component="div"
                >
                  Pizza Gallery
                </Typography>
              </Link>
            </NextLink>
            <div className={classes.grow}></div>
            <Switch
              id="switch"
              checked={darkMode}
              onChange={handleThemeChange}
              color="primary"
            ></Switch>
            <NextLink href="/login" passHref>
              <Link>
                <Typography>Login</Typography>
              </Link>
            </NextLink>
            <NextLink href="/cart" passHref>
              <Link>
                <Typography>Cart</Typography>
              </Link>
            </NextLink>
          </Toolbar>
        </AppBar>
        <Container className={classes.main}>{children}</Container>
        <footer className={classes.footer}>
          <Typography>all rights reserved © pizza gallery 2022</Typography>
        </footer>
      </ThemeProvider>
    </>
  );
};

export default Layout;

字符串
下面是商店:

import Cookies from "js-cookie";
import { createContext, useReducer } from "react";

export const Store = createContext();

const initialState = {
  darkMode: Cookies.get("darkMode") === "ON" ? true : false,
};

const reducer = (state, action) => {
  switch (action.type) {
    case "DARK_MODE_ON":
      return { ...state, darkMode: true };
    case "DARK_MODE_OFF":
      return { ...state, darkMode: false };
    default:
      return state;
  }
};

export const StoreProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  const value = { state, dispatch };
  return <Store.Provider value={value}>{children}</Store.Provider>;
};


/pages/_app.js

import { useEffect } from "react";
import "../styles/globals.css";
import { StoreProvider } from "../utils/Store";

function MyApp({ Component, pageProps }) {
  useEffect(() => {
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);
  return (
    <StoreProvider>
      <Component {...pageProps} />
    </StoreProvider>
  );
}

export default MyApp;


/pages/_document.js

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

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

MyDocument.getInitialProps = async (ctx) => {
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;
  ctx.renderPage = () => {
    return originalRenderPage({
      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
    });
  };
  const initialProps = await Document.getInitialProps(ctx);
  return {
    ...initialProps,
    styles: [
      ...React.Children.toArray(initialProps.styles),
      sheets.getStyleElement(),
    ],
  };
};

wfveoks0

wfveoks01#

如果未对该组件使用服务器端渲染,则可以尝试通过关闭ssr来导入该组件:

import dynamic from 'next/dynamic';
const Component = dynamic(() => 
    import('../components/path_to_component'), {
        ssr: false,
    });

字符串
希望这对你有帮助!

omhiaaxx

omhiaaxx2#

请确保页面在呈现客户端之前已挂载。您可以使用useState设置一个变量,如const [mount, setMount]= useState(false)
然后在页面加载时使用useEffect更改默认值。

useEffect(() => {
      setMount(true)

     }, [])

字符串
然后,您将像这样返回页面。

return(<>
{mount && (
//then display your code here
)}
</>)

相关问题