Jovan
Jovan

Reputation: 41

Why material UI is broken after a hard refresh in Nextjs

I have a problem with a new nextjs application, I have configured Material UI

Each time I refresh the page (hard) the style is not correct anymore, I have to redo modifications in each file to find my previous style...

I show you my _app and _document files

Thanks in advance for your help

_app.js

import React from "react";
import { CacheProvider } from "@emotion/react";
import { CssBaseline } from "@mui/material";
import { ThemeProvider } from "@mui/styles";

import createEmotionCache from "../styles/createEmotionCache";
import theme from "../config/MUITheme";

const clientSideEmotionCache = createEmotionCache();

const MyApp = ({ Component, emotionCache = clientSideEmotionCache, pageProps }) => (
    <CacheProvider value={emotionCache}>
        <ThemeProvider theme={theme}>
            <CssBaseline />
            <Component {...pageProps} />
        </ThemeProvider>
    </CacheProvider>
);

export default MyApp;

_document.js

import * as React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import createEmotionServer from "@emotion/server/create-instance";
import createEmotionCache from "../styles/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"
                    />
                </Head>
                <body>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        );
    }
}

MyDocument.getInitialProps = async (ctx) => {
    const originalRenderPage = ctx.renderPage;
    const cache = createEmotionCache();
    const { extractCriticalToChunks } = createEmotionServer(cache);

    /* eslint-disable */
    ctx.renderPage = () =>
        originalRenderPage({
            enhanceApp: (App) =>
                function EnhanceApp(props) {
                    return <App emotionCache={cache} {...props} />;
                },
        });

    /* eslint-enable */
    const initialProps = await Document.getInitialProps(ctx);
    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],
    };
};

Before refresh :

enter image description here

After refresh :

enter image description here

Environment :

You can reproduce with : https://codesandbox.io/s/throbbing-rain-72v10e

Upvotes: 2

Views: 1323

Answers (1)

user19963522
user19963522

Reputation:

I had the same problem for months and I realized even though your app.js and document.js is fine by hard refreshing it takes a bit to read theme(I still don't know why). My workaround for this was fully load the components that had this issue on client side. Components that don't need to be SSR you can turned off SSR feature for them. you can do this in two ways

  1. turn off SSR when importing:
export const component = dynamic(
  () => import('../components/component'),
  {
    ssr: false,
  }
);
  1. turn off ssr with a wrapper around component:
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,
});
return (
    <NoSSRWrapper>
    //your component code
      </NoSSRWrapper>
)

this way everything Waites and loads fully on client side therefore refreshing/hard refreshing doesn't affect the load of CSS.

this link was really helpful for me

Upvotes: 0

Related Questions