mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.97k stars 32.28k forks source link

Getting Warning: Prop className did not match In Material UI 3.9.6 with NextJS Ask #15073

Closed ankitpatelinitio closed 5 years ago

ankitpatelinitio commented 5 years ago

I used the below code to use AppBar, Toolbar, IconButton, Typography and some other elements of material UI and I applied classes to that element from props but classes not applied. e.g. root, menuButton, grow classes not applied. Also, I get some error in console.

Warning: Prop className did not match. Server: "MuiButtonBase-root-51 MuiIconButton-root-45 MuiIconButton-colorInherit-46 ButtonAppBar-menuButton-127" Client: "MuiButtonBase-root-51 MuiIconButton-root-45 MuiIconButton-colorInherit-46 ButtonAppBar-menuButton-3".

import React from "react"; import PropTypes from "prop-types"; import { withStyles } from "@material-ui/core/styles"; import AppBar from "@material-ui/core/AppBar"; import Toolbar from "@material-ui/core/Toolbar"; import Typography from "@material-ui/core/Typography"; import Button from "@material-ui/core/Button"; import IconButton from "@material-ui/core/IconButton"; import MenuIcon from "@material-ui/icons/Menu";

const styles = {
  root: {
    flexGrow: 1
  },
  grow: {
    flexGrow: 1
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20
  },
  appbackground: {
    backgroundColor: "#EC5D5D"
  }
};

function ButtonAppBar(props) {
  const { classes } = props;
  return (
    <div className={classes.root}>
      <AppBar position="static">
        <Toolbar>
          <IconButton
            className={classes.menuButton}
            color="inherit"
            aria-label="Menu"
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" color="inherit" className={classes.grow}>
            News
          </Typography>
          <Button href="#text-buttons" color="inherit">
            Login
          </Button>
        </Toolbar>
      </AppBar>
    </div>
  );
} 

 ButtonAppBar.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(ButtonAppBar);

Anyone, please suggest/help to fix this issue.
tkvw commented 5 years ago

Please take a look at https://github.com/mui-org/material-ui/tree/HEAD/examples/nextjs and follow this example to make styles work.

oliviertassinari commented 5 years ago

Yes, for v4, or https://github.com/mui-org/material-ui/tree/v3.x/examples/nextjs for v3.


We are well aware of the problem. We have recently introduced a SSR API, it creates more constraints, it's easier to use, it should reduce the probability of such issues. While you have to configure _document.js and _app.js in v3, configuring _document.js is enough with v4.

greygatch commented 5 years ago

The examples were removed?

oliviertassinari commented 5 years ago

The examples were removed?

Nothing was removed. It's in the git repository.

zhaoyao91 commented 5 years ago

Nothing was removed. It's in the git repository.

it may be a typo, try https://github.com/mui-org/material-ui/tree/master/examples/nextjs

enkemande commented 3 years ago

For anyone still facing this issue use NoSsr API for your components after the page has rendered.

gregg-cbs commented 3 years ago

Using this example: https://github.com/mui-org/material-ui/tree/master/examples/nextjs

in v4 breaks my entire layout. Its also not clear how to do it without emotion cache as theres a note that emotion could cause issues.

joeplaa commented 3 years ago

@gregg-cbs I have the same thing happening. Initially my app renders ok, but as soon as I refresh or browse to another page it breaks. I used this implementation: https://github.com/mui-org/material-ui/tree/v4.x/examples/nextjs-with-typescript

For me this started after upgrading to Next 11. It seems to be a known issue, but looks like most are focussing on MUI 5, but I can confirm this is also an issue with MUI 4. Maybe this will be fixed in one of these:

gregg-cbs commented 3 years ago

Yeah thats what i noticed, navigating breaks it.

I went back to my old implementation which was working until something happened. I realised it was an issue with nested html causing an inconsistent closing tag which caused this error.

hdoshi2 commented 2 years ago

For using Material UI with Next.js. The issue is deeper and related to server-side VS client-side rendering. It is explained well here: Rehydration

This helped resolve my issue: vercel/next.js#7322 (comment)

Basically, I wrapped components that need to be rendering on the client side, but creating this file ClientOnly.js:

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

I wrapped my _app.js file like this:

import UserProvider from "../context/user";
import Layout from "../components/Layout";
import ClientOnly from "./ClientOnly";

function MyApp({ Component, pageProps }) {
return (
    <UserProvider>
      <ClientOnly>
        <Layout />
        <Component {...pageProps} />
      </ClientOnly>
    </UserProvider>
);
}

export default MyApp;
mohammad-mustafa-24ourx commented 2 years ago

@hdoshi2

can't tell what I faced, and how many combinations I've used to fix this issue....even I downgraded my MUI v5 to material-ui v4, but still no luck....but yes this ClientOnly hasMounted strategy fixed my issue, thanks.

pradeepm93969 commented 2 years ago

@hdoshi2

After trying a dozen of solutions, this finally helped me. Thanks a lot.

Are there any side effects of using this?

macedomauriz commented 2 years ago

For using Material UI with Next.js. The issue is deeper and related to server-side VS client-side rendering. It is explained well here: Rehydration

This helped resolve my issue: vercel/next.js#7322 (comment)

Basically, I wrapped components that need to be rendering on the client side, but creating this file ClientOnly.js:

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

I wrapped my _app.js file like this:

import UserProvider from "../context/user";
import Layout from "../components/Layout";
import ClientOnly from "./ClientOnly";

function MyApp({ Component, pageProps }) {
return (
    <UserProvider>
      <ClientOnly>
        <Layout />
        <Component {...pageProps} />
      </ClientOnly>
    </UserProvider>
);
}

export default MyApp;

Wouldn't this prevent search engines to see the HTML?

chrisbucholz commented 2 years ago

One point the link mentions (https://www.joshwcomeau.com/react/the-perils-of-rehydration/) is that you don't need to wrap that <ClientOnly> around your whole App like that.

In our case, it was only a single (though often used) component that used styled-components which was causing the warning. Tracking that down and wrapping just that in <ClientOnly> helped silence the warning, while leaving the rest of the app's server side rendering (presumably) intact.

But great solution, and the explanatory link was super insightful.

AyonJD commented 1 year ago

I have spent nearly 5-6 hours on it and now you saved me. Thanks a lot.

WolfgangM81 commented 1 year ago

I spend close to 4 hours on this issue and to find your hint for NextJS13. Thank you so much!