Reputation: 41
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 :
After refresh :
Environment :
You can reproduce with : https://codesandbox.io/s/throbbing-rain-72v10e
Upvotes: 2
Views: 1323
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
export const component = dynamic(
() => import('../components/component'),
{
ssr: false,
}
);
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