{"id":413,"hash":"ce4c2f8332b012872f13fa47f259947dc35556adca82fce79a6cc67f87ffc917","pattern":"React + Material-UI - Warning: Prop className did not match","full_message":"I'm having difficulty with differences between client-side and server-side rendering of styles in Material-UI components due to classNames being assigned differently.\n\nThe classNames are assigned correctly on first loading the page, but after refreshing the page, the classNames no longer match so the component loses its styling. This is the error message I am receiving on the Console:\n\n  Warning: Prop className did not match. \n  Server: \"MuiFormControl-root-3 MuiFormControl-marginNormal-4\n  SearchBar-textField-31\" \n  Client: \"MuiFormControl-root-3 MuiFormControl-marginNormal-4\n  SearchBar-textField-2\"\n\nI've followed the Material-UI TextField example docs, and their accompanying Code Sandbox example, but I can't seem to figure out what is causing the difference between the server and client classNames.\n\nI experienced a similar issue when adding Material-UI Chips with a delete 'x' icon. The 'x' icon rendered with a monstrous 1024px width after refreshing. The same underlying issue being that icon was not receiving the correct class for styling.\n\nThere are a few questions on Stack Overflow addressing why the client and server might render classNames differently (e.g. need to upgrade to @Material-UI/core version ^1.0.0, using a custom server.js, and using Math.random in setState), but none of these apply in my case.\n\nI don't know enough to tell whether this Github discussion might help, but likely not since they were using a beta version of Material-UI.\n\nMinimal steps to reproduce:\n\nCreate project folder and start Node server:\n\nmkdir app\ncd app\nnpm init -y\nnpm install react react-dom next @material-ui/core\nnpm run dev\n\nedit package.json:\n\nAdd to 'scripts': \"dev\": \"next\",\n\napp/pages/index.jsx:\n\nimport Head from \"next/head\"\nimport CssBaseline from \"@material-ui/core/CssBaseline\"\nimport SearchBar from \"../components/SearchBar\"\n\nconst Index = () => (\n  <React.Fragment>\n    <Head>\n      <link\n        rel=\"stylesheet\"\n        href=\"https://fonts.googleapis.com/css?family=Roboto:300,400,500\"\n      />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n      <meta charSet=\"utf-8\" />\n    </Head>\n    <CssBaseline />\n    <SearchBar />\n  </React.Fragment>\n)\n\nexport default Index\n\napp/components/SearchBar.jsx:\n\nimport PropTypes from \"prop-types\"\nimport { withStyles } from \"@material-ui/core/styles\"\nimport TextField from \"@material-ui/core/TextField\"\n\nconst styles = (theme) => ({\n  container: {\n    display: \"flex\",\n    flexWrap: \"wrap\",\n  },\n  textField: {\n    margin: theme.spacing.unit / 2,\n    width: 200,\n    border: \"2px solid red\",\n  },\n})\n\nclass SearchBar extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = { value: \"\" }\n    this.handleChange = this.handleChange.bind(this)\n    this.handleSubmit = this.handleSubmit.bind(this)\n  }\n\n  handleChange(event) {\n    this.setState({ value: event.target.value })\n  }\n\n  handleSubmit(event) {\n    event.preventDefault()\n  }\n\n  render() {\n    const { classes } = this.props\n    return (\n      <form\n        className={classes.container}\n        noValidate\n        autoComplete=\"off\"\n        onSubmit={this.handleSubmit}\n      >\n        <TextField\n          id=\"search\"\n          label=\"Search\"\n          type=\"search\"\n          placeholder=\"Search...\"\n          className={classes.textField}\n          value={this.state.value}\n          onChange={this.handleChange}\n          margin=\"normal\"\n        />\n      </form>\n    )\n  }\n}\n\nSearchBar.propTypes = {\n  classes: PropTypes.object.isRequired,\n}\n\nexport default withStyles(styles)(SearchBar)\n\nVisit page in browser localhost:3000 and see this:\n\nred border around TextField component\n\nRefresh the browser and see this:\n\nTextField component's styles are gone\n\nNotice that the red border around TextField disappears.\n\nRelevant Libs:\n\n\"react\": 16.4.0\n\"react-dom\": 16.4.0\n\"next\": 6.0.3\n\"@material-ui/core\": 1.2.0","ecosystem":"npm","package_name":"node.js","package_version":null,"solution":"The problem is the SSR rendering in Next.js, which produces the style fragment before the page is rendered.\n\nUsing Material UI and Next.js (as the author is using), adding a file called _document.js solved the problem.\n\nAdjusted _document.js (as suggested here):\n\nimport React from 'react';\nimport Document, { Html, Head, Main, NextScript } from 'next/document';\nimport { ServerStyleSheets } from '@material-ui/styles'; // works with @material-ui/core/styles, if you prefer to use it.\nimport theme from '../src/theme'; // Adjust here as well\n\nexport default class MyDocument extends Document {\n  render() {\n    return (\n      <Html lang=\"en\">\n        <Head>\n          {/* Not exactly required, but this is the PWA primary color */}\n          <meta name=\"theme-color\" content={theme.palette.primary.main} />\n        </Head>\n        <body>\n          <Main />\n          <NextScript />\n        </body>\n      </Html>\n    );\n  }\n}\n\n// `getInitialProps` belongs to `_document` (instead of `_app`),\n// it's compatible with server-side generation (SSG).\nMyDocument.getInitialProps = async (ctx) => {\n  // Resolution order\n  //\n  // On the server:\n  // 1. app.getInitialProps\n  // 2. page.getInitialProps\n  // 3. document.getInitialProps\n  // 4. app.render\n  // 5. page.render\n  // 6. document.render\n  //\n  // On the server with error:\n  // 1. document.getInitialProps\n  // 2. app.render\n  // 3. page.render\n  // 4. document.render\n  //\n  // On the client\n  // 1. app.getInitialProps\n  // 2. page.getInitialProps\n  // 3. app.render\n  // 4. page.render\n\n  // Render app and page and get the context of the page with collected side effects.\n  const sheets = new ServerStyleSheets();\n  const originalRenderPage = ctx.renderPage;\n\n  ctx.renderPage = () =>\n    originalRenderPage({\n      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),\n    });\n\n  const initialProps = await Document.getInitialProps(ctx);\n\n  return {\n    ...initialProps,\n    // Styles fragment is rendered after the app and page rendering finish.\n    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],\n  };\n};","confidence":0.95,"source":"stackoverflow","source_url":"https://stackoverflow.com/questions/50685175/react-material-ui-warning-prop-classname-did-not-match","votes":90,"created_at":"2026-04-19T04:51:06.843336+00:00","updated_at":"2026-04-19T04:51:06.843336+00:00"}