next.js 页面刷新时材质界面样式消失

stszievb  于 2022-12-18  发布在  其他
关注(0)|答案(3)|浏览(291)

我正在将我的React应用转换为Next应用,以利用SSR。我正在使用Material UI 4进行造型。
我已经按照材质UI文档实现了_app.js_document.js文件,但问题是当页面第一次加载时,材质UI样式没有被应用,但当我在组件中进行一些更改时,只有所有样式出现。
我是在参考thisthis答案和Internet上的其他资源后才发布此问题的

_应用程序.js

import '@assets/fonts/global.css';
import React, {useState, useEffect} from "react";
import Layout from "@layout/Layout";
import Footer from "@layout/Footer/Footer";
import Header from "@layout/Header/Header";
//import Sidebar from "@layout/Sidebar/Sidebar";

//Material UI
import CssBaseline from "@material-ui/core/CssBaseline";
import theme from "@helper/theme/theme";
import {ThemeProvider as MuiThemeProvider} from "@material-ui/styles";

//Redux
import {wrapper} from "@store/store";

function MyApp({Component, pageProps}) {

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

    return (

        <>
            <MuiThemeProvider theme={theme}>
                <CssBaseline/>
                <Header/>
                <Layout>
                    <Component {...pageProps} />
                </Layout>
                <Footer/>
            </MuiThemeProvider>
        </>
    );
}

export default wrapper.withRedux(MyApp);

_文件.js

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

export default class MyDocument extends Document {

    render() {

        return (
            <Html lang="en">
                <Head>
                    <meta name="theme-color" content={theme.palette.primary.main} />
                </Head>
                <body>
                    <Main/>
                    <NextScript/>
                </body>
            </Html>
        );
    }
}

MyDocument.getInitialProps = async (ctx) => {

    console.log('DOC Called');

    // 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()],
    };
};
  • 注意:即使按照材质ui文档使用_app.js_document.js文件后,我仍然在控制台中收到以下警告 *
next-dev.js?3515:25 Warning: Prop `className` did not match.

jogvjijk

jogvjijk1#

可能是样式不匹配的问题?如果使用create-next-app,则默认情况下reactStrictMode处于打开状态
根据以下链接这里:https://github.com/mui/material-ui/issues/18018材质UI v4与严格模式不兼容,因此在此之前,您可以尝试禁用reactStrictMode或使用材质UI v5。

// in next.config.js
module.exports = {
  reactStrictMode: false
}

如果我误解了什么,我道歉!

vjhs03f7

vjhs03f72#

添加_document.tsx到你的项目和粘贴这一个.添加主题 meta标记和用户ServerStyleSheet以及

import createEmotionServer from '@emotion/server/create-instance';
import { ServerStyleSheets } from '@mui/styles';
import Document, { Head, Html, Main, NextScript } from 'next/document';
import * as React from 'react';
import light from 'styles/theme/light';
import createEmotionCache from 'utils/createEmotionCache';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang='en'>
        <Head>
          <link
            rel='stylesheet'
            href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap'
          />
          <meta name='theme-color' content={light.palette.primary.main} />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site 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

  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  // You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
  // However, be aware that it can have global side effects.
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  /* eslint-disable */
  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App: any) => (props) =>
        sheets.collect(<App emotionCache={cache} {...props} />),
    });
  /* eslint-enable */

  const initialProps = await Document.getInitialProps(ctx);
  // This is important. It prevents emotion to render invalid HTML.
  // See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [
      ...React.Children.toArray(initialProps.styles),
      ...emotionStyleTags,
    ],
  };
};

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  // reactStrictMode: true,
  lib: ['es6', 'dom'],
  noImplicitAny: true,
  noImplicitThis: true,
  strictNullChecks: true,
  images: {
    domains: ['rickandmortyapi.com'],
    loader: 'custom',
    path: '/static/images/',
  },
  env: {
    BASE_URL: process.env.NEXT_PUBLIC_BASE_URL,
  },
};

module.exports = nextConfig;
o2rvlv0m

o2rvlv0m3#

我有同样的问题好几天了,以下是我做的事情:

  • 确保我的主题在src文件夹中
  • 我使用这个文件夹结构和_document.js_app.jsindex.js提供在材料official example。确保遵循每一个细节提供在每一个这些文件。他们的方式的东西是进口,他们的文件夹结构,主题和...
  • 我关闭了SSR的组件,如页脚或一些其他静态数据,不需要SSR添加nossr Package 器。我有断点在我的主题,导致打破刷新css,所以关闭SSR时,不需要使组件完全加载到客户端:
import React from 'react';

import dynamic from 'next/dynamic';

const NoSSRWrapper = props => <React.Fragment>{props.children}</React.Fragment>;
export default dynamic(() => Promise.resolve(NoSSRWrapper), {
  ssr: false,
});
import NoSSRWrapper from '../../components/NoSSRWrapper';
function func() {
  return (
    <NoSSRWrapper>
//your component
   </NoSSRWrapper>
    )
}

另外,我建议不要用redux Package _app.js,而是使用<Provider store={store}>,类似于这样(_app.js的小细节很重要)

import store from '../utils/store';
  return (
  <Provider store={store}>
        <ThemeProvider theme={theme}>
          <Layout>
            <Component {...pageProps} />
          </Layout>
        </ThemeProvider>
      </Provider>
)

相关问题