Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm creating a NextJS app that uses React Material-Ui and I'm getting the
Prop 'className' did not match.
error, even though I changed my
_app.tsx
and
_document.tsx
according to the documentation.
My
_app.tsx
:
// pages/_app.tsx
/* eslint-disable react/jsx-props-no-spreading */
import { FC, useEffect } from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/core/styles';
import { AppProps } from 'next/app';
import Head from 'next/head';
import { defaultTheme as theme } from '../src/themes';
const MyApp: FC<AppProps> = ({ Component, pageProps }) => {
useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}, []);
return (
<title>My App</title>
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
export default MyApp;
My _document.tsx
:
import React from 'react';
import Document, {
Html,
Head,
Main,
NextScript,
DocumentProps,
DocumentContext,
} from 'next/document';
import { ServerStyleSheets } from '@material-ui/core/styles';
import { defaultTheme as theme } from '../src/themes';
export default class MyDocument extends Document {
static getInitialProps = async (ctx: DocumentContext) => {
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(),
render() {
return (
<Html lang="en">
{/* PWA primary color */}
name="theme-color"
content={theme.palette.primary.main}
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,800,900&display=swap"
</Head>
<Main />
<NextScript />
</body>
</Html>
Browser Console Error:
Warning: Prop `className` did not match. Server: "MuiBox-root MuiBox-root-10" Client: "MuiBox-root MuiBox-root-13"
StyledComponent@webpack-internal:///./node_modules/@material-ui/styles/esm/styled/styled.js:95:22
Grid@webpack-internal:///./node_modules/@material-ui/core/esm/Grid/Grid.js:236:29
WithStyles@webpack-internal:///./node_modules/@material-ui/styles/esm/withStyles/withStyles.js:61:25
Grid@webpack-internal:///./node_modules/@material-ui/core/esm/Grid/Grid.js:236:29
WithStyles@webpack-internal:///./node_modules/@material-ui/styles/esm/withStyles/withStyles.js:61:25
Container@webpack-internal:///./node_modules/@material-ui/core/esm/Container/Container.js:85:17
WithStyles@webpack-internal:///./node_modules/@material-ui/styles/esm/withStyles/withStyles.js:61:25
StyledComponent@webpack-internal:///./node_modules/@material-ui/styles/esm/styled/styled.js:95:22
StyledComponent@webpack-internal:///./node_modules/@material-ui/styles/esm/styled/styled.js:95:22
Home@webpack-internal:///./pages/index.tsx:93:17
ThemeProvider@webpack-internal:///./node_modules/@material-ui/styles/esm/ThemeProvider/ThemeProvider.js:42:18
MyApp@webpack-internal:///./pages/_app.tsx:37:19
ErrorBoundary@webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ErrorBoundary.js:26:47
ReactDevOverlay@webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ReactDevOverlay.js:86:20
Container@webpack-internal:///./node_modules/next/dist/client/index.js:254:20
AppContainer@webpack-internal:///./node_modules/next/dist/client/index.js:750:18
Root@webpack-internal:///./node_modules/next/dist/client/index.js:889:19
I just can't figure out what's happening. Any suggestion?
–
–
Setting 'reactStrictMode' to false inside next.config.js seems to solve the issue
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: false,
I don't really know why that's the case. If anyone knows, feel free to explain in the comments
–
–
Only this worked for me https://github.com/vercel/next.js/issues/7322#issuecomment-987086391
import React from "react";
const ClientOnly = ({ children, ...delegated }) => {
const [hasMounted, setHasMounted] = React.useState(false);
React.useEffect(() => {
setHasMounted(true);
}, []);
if (!hasMounted) return null
return (
<React.Fragment {...delegated}>
{children}
</React.Fragment>
export default ClientOnly
wrap the form ->
<ClientOnly>
<SomeComponnet/>
</ClientOnly>
Next.js supports lazy loading React components with next/dynamic. In the main Layout component you can add this wrapper and export it.
In Layout.jsx
import dynamic from 'next/dynamic'
now wrap your export component with dynamic as below
export default dynamic(() => Promise.resolve(Layout), { ssr: false })
now this component can delay hydration until the Suspense boundary is resolved.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.