Warning: Prop `className` did not match. when using styled components with semantic-ui-react
Asked Answered
N

20

99

I use this code to margin my Button from top:

const makeTopMargin = (elem) => {
    return styled(elem)`
        && {
            margin-top: 1em !important;
        }
    `;
}

const MarginButton = makeTopMargin(Button);

and whenever i use MarginButton node, I get this error: Warning: PropclassNamedid not match. Server: "ui icon left labeled button sc-bwzfXH MjXOI" Client: "ui icon left labeled button sc-bdVaJa fKCkqX"

You can see this produced here.

What should I do?

Nationalism answered 10/8, 2018 at 17:9 Comment(7)
The link you shared is to port :3000 on an IP address. Unless you have made that IP address available to public traffic and have a currently running web server there, nobody will be able to access what you are running. Try creating a minimal example of your problem using a tool like codesandbox instead. codesandbox.ioPresocratic
Sorry, that ip is actually a vps but it is not running right now for a reason. I will try to reproduce it now.Folliculin
@Presocratic Please see codesandbox.io/s/xvmq9jjzzqFolliculin
I am looking at your console and there is no proptype warning for className.Presocratic
I think it happens only in development environment. I can't reproduce it online.Folliculin
I have this error happening two pages, none of the answers helped, did you end resolving this ?Lynnet
You only need to add this line of code into your next.config.js file module.exports = { compiler: { styledComponents: true, } }Antin
O
122

Or you could just add this to your next.config.js. This also makes it so next-swc (speedy web compiler) works to reduce build times. See more here.

// next.config.js
module.exports = {
  compiler: {
    // Enables the styled-components SWC transform
    styledComponents: true
  }
}
Osteoclast answered 21/12, 2021 at 1:12 Comment(4)
This worked well for me. All I had to do afterwards was restart my local server. Based on my limited understanding, it seems that this experimental value prevents mismatched classes created by styled-components as it is processed by the server and then the client.Aleman
As of Feb 2022 it appears that this no longer "experimental". As @Abhilash Rathod points out in his answer (https://mcmap.net/q/215887/-warning-prop-classname-did-not-match-when-using-styled-components-with-semantic-ui-react), it now works under the compiler key instead of experimental.Ideatum
I edited the answer to reflect this (correct) comment.Cambrai
I'm using Next/SWC, and this fix did not fix the issue for me.Cambrai
A
78

This warning was fixed for me by adding an .babelrc file in the project main folder, with the following content:

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

See following link for an example: https://github.com/nblthree/nextjs-with-material-ui-and-styled-components/blob/master/.babelrc

Adhamh answered 21/9, 2020 at 5:54 Comment(6)
This worked for me after I npm i babel-preset-nextCurtsey
So this works for me, but what's the explanation for this ?Rosiorosita
After install npm i babel-preset-next I couldn't start my project :(Facesaving
i used babel-plugin-styled-components package and RESTART project. it worksIronist
Next no longer uses Babel; what's the new version of this answer?Cambrai
didn't work for me - "next": "^13.4.2"Aspic
H
34

You should install the babel plugin for styled-components and enable the plugin in your .babelrc

npm install --save-dev babel-plugin-styled-components

.babelrc

{
  "plugins": [
    [
      "babel-plugin-styled-components"
    ]
  ]
}
Haag answered 19/1, 2019 at 22:47 Comment(0)
H
32

The main reason I am posting this answer to help people understand the tradeoff. When we're using .babelrc in next project it's going to opt of SWC compiler which is based on Rust (Learn More).

It's going to show message something like this when you opt for custom bable config.

info  - Disabled SWC as replacement for Babel because of custom Babel configuration ".babelrc"

I did more digging on this to only find out following! Ref

Next.js now uses Rust-based compiler SWC to compile JavaScript/TypeScript. This new compiler is up to 17x faster than Babel when compiling individual files and up to 5x faster Fast Refresh.

So tradeoff was really huge, we can lose significant amout of performance. So I found a better solution which can solve this issue and keep SWC as default compiler.

You can add this experimental flag in your next.config.js to prevent this issue. Ref

// next.config.js

module.exports = {
  compiler: {
    // ssr and displayName are configured by default
    styledComponents: true,
  },
}
Heraldic answered 13/2, 2022 at 11:10 Comment(0)
I
15

For Old versions form Nextjs < 12, Go to next.config.js file and add this line inside nextConfig object:

  experimental: {
   // Enables the styled-components SWC transform
   styledComponents: true
  }

for new NextJs above 12:

  compiler: {
    styledComponents: true
  }

if that does not work you need to make an NO SSR component wrapper like this:

// /components/NoSsr.js

import dynamic from 'next/dynamic'

const NoSsr = ({ children }) => <>{children}</>

export default dynamic(() => Promise.resolve(NoSsr), { ssr: false })

Then you need to add warp No SSR with your component like this:

// /pages/index.js

import NoSsr from '../components/NoSsr'
import CircleButton from '../components/buttons/CircleButton'

const HomePage = () => {
  return (
    <>
      <p>Home Page Title</p>
      <NoSsr>
       {/* Here your styled-component */}
        <makeTopMargin ele={...} />
      </NoSsr>
    </>
  )
}
Im answered 1/8, 2022 at 0:40 Comment(1)
Try this, it works. The no ssr approach solves things.Reitareiter
D
6

If you have already added babel plugins, delete the .next build folder & restart the server again

credit: Parth909 https://github.com/vercel/next.js/issues/7322#issuecomment-912415294

Decoct answered 24/9, 2021 at 8:44 Comment(0)
V
5

I was having the exact same issue and it was resolved by doing:

npm i babel-preset-next
npm install --save -D babel-plugin-styled-components

and adding this to .babelrc file:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}
Viki answered 1/9, 2021 at 6:34 Comment(0)
V
4

Styled components server side rendering

Server Side Rendering styled-components supports concurrent server side rendering, with stylesheet rehydration. The basic idea is that everytime you render your app on the server, you can create a ServerStyleSheet and add a provider to your React tree, that accepts styles via a context API.

This doesn't interfere with global styles, such as keyframes or createGlobalStyle and allows you to use styled-components with React DOM's various SSR APIs.


import { renderToString } from 'react-dom/server'
import { ServerStyleSheet } from 'styled-components'

const sheet = new ServerStyleSheet()
try {
  const html = renderToString(sheet.collectStyles(<YourApp />))
  const styleTags = sheet.getStyleTags() // or sheet.getStyleElement();
} catch (error) {
  // handle error
  console.error(error)
} finally {
  sheet.seal()
}


import { renderToString } from 'react-dom/server'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'

const sheet = new ServerStyleSheet()
try {
  const html = renderToString(
    <StyleSheetManager sheet={sheet.instance}>
      <YourApp />
    </StyleSheetManager>
  )
  const styleTags = sheet.getStyleTags() // or sheet.getStyleElement();
} catch (error) {
  // handle error
  console.error(error)
} finally {
  sheet.seal()
}

In my case as im using nextjs

import Document, { Head, Main, NextScript } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static getInitialProps({ renderPage }) {
    const sheet = new ServerStyleSheet();
    const page = renderPage(App => props =>
      sheet.collectStyles(<App {...props} />)
    );
    const styleTags = sheet.getStyleElement();
    return { ...page, styleTags };
  }

  render() {
    return (
      <html>
        <Head>{this.props.styleTags}</Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Vinasse answered 8/1, 2020 at 7:48 Comment(1)
I have tried to add styled-components to my Next.js project. It still doesn't work. My issue is that when I reload the page deployed by npm run dev, it throws the error of server not matching the styles at the client end. I have even used the babel-plugin-styled-component plugin. Nothing seems to be working. Can you suggest something? Thanks!Snowblind
S
4

I have solved this issue following these steps.

  1. Create a file named .babelrc in the root directory and configure the .babelrc file.
  2. delete the .next build folder(It stores some caches).
  3. Restart the server.
  4. Hot reload the browser.

.babelrc configuration file

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true,
                "displayName": true,
                "preprocess": false
            }
        ]
    ]
}
Sylvanite answered 22/10, 2021 at 11:59 Comment(0)
P
3

PropType errors are runtime errors that will let you know that the data expected being passed to a prop is not what is expected. It looks like the className prop that is being set on your component is not the same when the component is rendered on the server and when it is then rendered in the client's DOM.

Since it looks like you are using server side rendering, you need to make sure that your class names are deterministic. That error is showing you the class that is being created by your styled-components library on the server and how it is different from the DOM. For libraries that do not normally have deterministic class names, you need to look at advanced configurations. Take a look at the styled-components documentation regarding specificity as it pertains to SSR.

Presocratic answered 14/8, 2018 at 14:42 Comment(1)
Is there a captureable event associated with the component/element comparison that triggers this warning? In my case, the warning is triggered when my own JavaScript adds classes to DOM elements before React finishes updating components in the DOM on first load. If I knew the event associated with the comparison activity and could listen for it, I could defer my own DOM manipulations until React is finished.Iredale
G
2

//1.  I got an error when using material-ui with Next.js 


/********************************************* */

//2.  The code I imported was like this  : 


const useStyles = makeStyles({
    root: {     //  root must change 
        width: 100 ,
    }
});

const Footer = () => {
    const classes = useStyles();

    return (
        <div className={classes.root} > { /*  root must change */}
            <p> footer copyright @2021 </p>
        </div>
    )

}
export default Footer;


/********************************************* */

//3. I changed the code like this :


const useStyles = makeStyles({
    footer: {   //  changed here to footer
        width: "100%",
        backgroundColor: "blue !important"
    }
});

const Footer = () => {
    const classes = useStyles();

    return (
        <div className={classes.footer} > { /*  changed here to footer */}
            <p> footer copyright @2021 </p>
        </div>
    )

}
export default Footer;



// I hope it works
Glowing answered 25/5, 2021 at 14:11 Comment(0)
L
2

I'm using NextJS 12 and encountered the same issue, well error in the console, code was working ok.
I fixed it by creating a .babelrc file at the root of the project and add:

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true,
                "displayName": true,
                "preprocess": false
            }
        ]
    ]
}
Lepley answered 4/2, 2022 at 20:47 Comment(0)
A
2

Styled Components have full, core, non-experimental support in Next now (2022), but you have to turn them on:

Add the following to your next.config.js:

compiler: {
  styledComponents: true,
},

My full, mostly vanilla, next.config.js now looks like this:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  compiler: {
    // Enables the styled-components SWC transform
    styledComponents: true,
  },
}

module.exports = nextConfig

https://nextjs.org/blog/next-12-1#improved-swc-support

Aveyron answered 1/8, 2022 at 7:29 Comment(0)
R
1

This answer is for those who are using NextJs version > v12.0.1 and SWC compiler. You don't have to add _document.js file nor do babel related stuff anymore since it has been replaced by SWC compiler since v12.0.0. Only that your next.config.js file should look like the following since NextJs supports styled components after v12.1.0 and restart the server and it should work: more here

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  // add the following snippet
  compiler: {
    styledComponents: true,
  },
};

module.exports = nextConfig;
Ramakrishna answered 30/6, 2022 at 12:25 Comment(0)
N
1

I followed all the other advice, around setting up .babelrc (or .babelrc.js), but noticed this message in the Next.js docs:

When css-in-js libraries are not set up for pre-rendering (SSR/SSG) it will often lead to a hydration mismatch. In general this means the application has to follow the Next.js example for the library. For example if pages/_document is missing and the Babel plugin is not added.

That linked to this file, showing that I needed to add this to pages/_document.tsx to:

// if you're using TypeScript use this snippet:

import React from "react";

import Document, {DocumentContext, DocumentInitialProps} from "next/document";
import {ServerStyleSheet} from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext,
  ): Promise<DocumentInitialProps> {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

A blog post by Raúl Sánchez also mentions this solution, linking to the JavaScript version if you're not using TS (pages/_document.js):

// if you're *not* using TypeScript use this snippet:

import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}
Nebraska answered 8/10, 2022 at 10:32 Comment(0)
A
1

If the error for adding the class name "scroll-smooth" in the <html> tag or <body> tag then the error is fixed by adding suppressHydrationWarning={true}

You can also check this: https://nextjs.org/docs/messages/react-hydration-error

<HTML
    lang="en"
    className="!scroll-smooth"
    suppressHydrationWarning={true}
>

or

<body
    suppressHydrationWarning={true}
>
Aubree answered 1/12, 2023 at 19:10 Comment(0)
S
0

If you are using create-react-app, you can use thi solution.

File called styled.ts

import styled from 'styled-components/macro';
import { css } from 'styled-components';

export const ListRow = styled.div`
  ...
  ...
`

Based on the files name, the prefix will be as following.

`${file_name}__{styled_component_name} ${unique_id}`

Meaning when implemented it will have the following classname
enter image description here

Although it would be nice to specify from where the first prefix would be taken from, meaning instead of file_name, we take folder_name. I currently dont know the solution for it.

Seedtime answered 7/12, 2021 at 11:50 Comment(0)
N
0

To expand on C. Molindijk's answer, this error occurs when server-side class is different from client-side because styled-components generates its own unique class Id's. If your Next app is server-side rendered, then his answer is probably correct. However, Next.Js is by default statically generated, so unless you enabled SSR, configure it like this without ssr set to true:

{
  "presets": ["next/babel"],
  "plugins": [["styled-components"]]
}
Nip answered 30/5, 2022 at 16:57 Comment(0)
G
0

I got this problem when using MUI, and i solved it, instead of import like this import { TableCell } from '@mui/material';, change to import TableCell from '@mui/material/TableCell'; .the warning Prop className did not match will be disapeared. worked for me!

Gilford answered 29/11, 2023 at 5:43 Comment(0)
A
0

This is what worked for me:

Replace:

import { styled } from "styled-components";

With:

import styled from "styled-components";

https://github.com/vercel/next.js/issues/46605#issuecomment-1639900755

Aspic answered 26/2, 2024 at 18:47 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.