vercel / next.js

The React Framework
https://nextjs.org
MIT License
122.51k stars 26.22k forks source link

Warning: Prop className did not match. #7322

Closed th0th closed 4 years ago

th0th commented 5 years ago

Examples bug report

Example name

with-styled-components

Describe the bug

Also posted here: #2538

Using css prop introduced with styled-components v4 causes Warning: Prop className did not match..

To Reproduce

Add any HTML element with css prop.

Expected behavior

Correctly styled rendering on the server side without any warnings.

Screenshots

57497472-7b657c00-72e0-11e9-84c5-e7e5fa0d351c

System information

Additional context

Here is an example I created to demonstrate the issue: https://codesandbox.io/embed/jlwvwyy0ow

Open this and refresh once the building is done: https://jlwvwyy0ow.sse.codesandbox.io/

iaremarkus commented 4 years ago

Brand new Next project using create-next-app, and StyledComponents 5.1.1 and having the same error a few lines of code in.

How is this closed? :sadpanda:

JorgeSivil commented 4 years ago

There's a way to overcome this:

useState for the class name, and useEffect to change it.

The only con is that you'll not have the class applied in the HTML returned from the server

const Header = ({ brandName, className }) => {
...
  const [styledClassName, setStyledClassName] = useState(
    classNames({
      [styles.main]: true,
      [brandStyles.header]: brandId !== 1,
      [brandStyles[brandName]]: brandId !== 1,
    }),
  );
 ...
   useEffect(() => {
    setStyledClassName(
      classNames({
        [styles.main]: true,
        [className]: true,
        [brandStyles.header]: brandId !== 1,
        [brandStyles[brandName]]: brandId !== 1,
      }),
    );
  }, []);
 ...
 return (
    <header
      className={styledClassName}
  ...
  )

...
 const styledHeader = styled(Header)`
  background-image: url('/static/img/brand/${(props) => props.brandName}/header/mobile/background.jpg');
  @media (min-width: 1240px) {
    background-image: url('/static/img/brand/${(props) => props.brandName}/header/background.jpg');
  }
`;
hypo-thesis commented 4 years ago

It has been 2 years since this issue has been raised and still this exists. Nextjs shows very little attention to users concerns which makes this library unreliable. I am already looking into alternatives.

adventurini commented 4 years ago

It has been 2 years since this issue has been raised and still this exists. Nextjs shows very little attention to users concerns which makes this library unreliable. I am already looking into alternatives.

What is this Walmart?? This is a whiny sentiment that provides absolutely no benefit to anyone. If you want to help, then contribute. When you comment on an issue thread, it pings everyone your toxic attitude. I only hope you find another framework so I don't have to read another one of your naggy comments.

torayeff commented 4 years ago

We still have the same issue. In my case, the client and server return different classes (different id probably) and the appearance breaks. I just restart the server and the warning goes away.

timneutkens commented 4 years ago

If you're running into this and using a CSS-in-JS library like styled-components / emotion / Material UI make sure you configure it correctly. Here's the examples:


It has been 2 years since this issue has been raised and still this exists. Nextjs shows very little attention to users concerns which makes this library unreliable. I am already looking into alternatives.

Let's break down the things you're claiming:

It has been 2 years since this issue has been raised and still this exists.

The warning you're seeing is a React hydration warning. The warning shows when the pre-rendered (SSR or SSG) response differs from the client-side React tree. In this case the className generated during pre-rendering is different from the one client-side. Generally this is caused by not configuring the CSS-in-JS library for pre-rendering, e.g. in case of styled-components you have to add this bit: https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js#L5-L29 which allows for tracking what styled-components were rendered and publishing those into a <style> tag server-side.

Nextjs shows very little attention to users concerns which makes this library unreliable

timneutkens commented 4 years ago

What is this Walmart?? This is a whiny sentiment that provides absolutely no benefit to anyone. If you want to help, then contribute. When you comment on an issue thread, it pings everyone your toxic attitude. I only hope you find another framework so I don't have to read another one of your naggy comments.

I appreciate the defending and understand why you're annoyed by the comment as it doesn't add anything to this thread. Let's remember to be welcoming even when someone shares their opinion and that opinion is unrelated to the thread. The best thing we can do is give them all the information (see post above and hope it changes their mind. Also pointing to create a discussion would be a good one: https://github.com/vercel/next.js/discussions

If you want to help, then contribute

Specifically to this, people don't have to contribute. The best thing people can do is create a full reproduction (e.g. a GitHub repository) of their specific issue. This GitHub issue as-is is not a single issue, it's probably more like 10+ different issues given that you're all using different libraries (styled-components, emotion, material ui, etc) and they all work differently when pre-rendered and need additional configuration.

I've already posted that in the thread before: https://github.com/vercel/next.js/issues/7322#issuecomment-496219766 https://twitter.com/timneutkens/status/1154351052973625346

songyule commented 4 years ago

It has been 2 years since this issue has been raised and still this exists. Nextjs shows very little attention to users concerns which makes this library unreliable. I am already looking into alternatives.

you can look the issues fixed my problem

d3vzr commented 4 years ago

Had a similar error Just solved it by changing class to className
I forgot and used class instead of className

bel7aG commented 4 years ago

Fixed on @1.11.0-0 "babel-plugin-styled-components": "^1.11.0-0",

in .babelrc: { "env": { "development": { "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]], "presets": ["next/babel"] }, "production": { "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]], "presets": ["next/babel"] } }, "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]] }

maktouch commented 4 years ago

Updating "babel-plugin-styled-components": "^1.11.0-0" worked for me. Thanks!

Pascal-Lohscheidt commented 4 years ago

For me, I just had to update styled-components and the problem was solved

nazmifeeroz commented 4 years ago

hey all,

doing this will work:

Install babel plugin: yarn add --dev babel-plugin-styled-components

create new file .babelrc in your root project folder and add this:

{
    "env": {
      "development": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      },
      "production": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      }
    },
    "plugins": [
      [
        "babel-plugin-styled-components",
        { "ssr": true, "displayName": true, "preprocess": false }
      ]
    ]
}
giovannabadaro commented 4 years ago

Updating "babel-plugin-styled-components": "^1.11.0-0" worked for me

yayxs commented 4 years ago

I have the same problem

Warning: Prop className did not match. Server: "MuiBox-root MuiBox-root-10" Client: "MuiBox-root MuiBox-root-6"

marcusfrdk commented 4 years ago

I had the same problem, thinking it could be something with the framework. However, playing with my code I discovered that the problem occurred once I imported components which were the "main" of the local package.json of that respective folder (i.e /src/components/component/package.json). I removed this and restarted the server. This solved the problem for me, both in development and production and has not appeared since.

pie6k commented 4 years ago

@giovannabadaro not sure, but 1.11.0-0 actually is older than 1.10 :O

image

zer0blockchain commented 3 years ago

This fixed it for me https://github.com/MarchWorks/nextjs-with-material-ui-and-styled-components/blob/master/.babelrc

ocavue commented 3 years ago

Hi @timneutkens.

I still have this issue, so I create a full reproduction repository: https://github.com/ocavue/mui-next-classname-issue. You can find the reproduction steps in the repo README.

It's "cropped version" of a real project, with only the code related to this issue. I can provide more detailed information if you guys cannot reproduce the problem.

timneutkens commented 3 years ago

Hi @timneutkens.

I still have this issue, so I create a full reproduction repository: ocavue/mui-next-classname-issue. You can find the reproduction steps in the repo README.

It's "cropped version" of a real project, with only the code related to this issue. I can provide more detailed information if you guys cannot reproduce the problem.

You didn't configure material-ui correctly per their example: https://github.com/mui-org/material-ui/blob/master/examples/nextjs/pages/_document.js#L27-L68

Missing in your application: https://github.com/ocavue/mui-next-classname-issue/blob/master/src/pages/_document.tsx

ocavue commented 3 years ago

You didn't configure material-ui correctly per their example: https://github.com/mui-org/material-ui/blob/master/examples/nextjs/pages/_document.js#L27-L68

This works for me! Thank you so much.

I did miss this part when I check their example. I just submitted a PR to material-ui to add some troubleshooting in their document and hope this will saves others time in the feature.

adriangzz commented 3 years ago

I'm having this problem with use-dark-mode , anybody else?

songyule commented 3 years ago

reference: https://github.com/vercel/next.js/tree/canary/examples/with-styled-components Hi @timneutkens. I configured the file .babelrc and it can work normally. so I have a question, What is the effect of adding sheet.getStyleElement() in _document.jsx

pie6k commented 3 years ago

I'm having this problem with use-dark-mode , anybody else?

well, that's reasonable. Server doesn't know if you have dark mode enabled.

Solution could be to save 'last mode' on server somehow and make this hook using this value on server side

owen26 commented 3 years ago

This issue has always been a headache to me with all of my next.js projects. I thought I've done all workarounds provided on the internet but the same error pops up occasionally on different places.

The tricky thing is it seems not always happening, but when you start thinking you've finally nailed it then it came back again from nowhere...

My latest discovery is that under some circumstances, the babel config option of "preprocess": false is a must for styled-components plugin. Some examples on the internet don't have it. Which is a bit of misleading as I thought it's not necessary.

rodolphoasb commented 3 years ago

I'm having this error but I don't use styled components. I'm using Tailwind CSS. Somebody has any thoughts about how can I solve this?

Basically what I'm doing is a conditional rendering of the navbar based on the logged status of a user. To se if the user is logged in I'm checking if there is a specific cookie set.

joshuap233 commented 3 years ago

FYI - also encountering this problem with Prism.js

Hello, have you found a solution?

dimosmera commented 3 years ago

This still happens. Adding this bit https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js#L5-L29 does not work for me.

ghost commented 3 years ago

@dimosmera make sure to follow these steps 👇

hey all,

doing this will work:

Install babel plugin: yarn add --dev babel-plugin-styled-components

create new file .babelrc in your root project folder and add this:

{
    "env": {
      "development": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      },
      "production": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      }
    },
    "plugins": [
      [
        "babel-plugin-styled-components",
        { "ssr": true, "displayName": true, "preprocess": false }
      ]
    ]
}
timcash commented 3 years ago

Replicated with this repo https://github.com/timcash/row-test Trying to use Next.js and a spreadsheet component from https://rowsncolumns.app/ Looks like it uses emotion but none of the fixes mentioned so far work I get this in the console

downshift: You must apply the ref prop "ref" from getRootProps onto your root element.

and

Warning: Prop `className` did not match. Server: "css-1fahozo" Client: "css-ec6wvp"
    in button (created by Context.Consumer)
    in PseudoBox (created by Button)
    in Button (created by Context.Consumer)
    in EmotionCssPropInternal (created by IconButton)
    in IconButton (created by ForwardRef)
    in ForwardRef (created by Tooltip)
    in Tooltip (created by Context.Consumer)
    in Styled(Tooltip)
    in div (created by Context.Consumer)
    in Box (created by Flex)
    in Flex
    in div (created by Context.Consumer)
    in Box (created by Toolbar)
    in Toolbar (created by Context.Consumer)
    in Styled(Toolbar)
    in Unknown (created by ForwardRef)
    in div (created by Context.Consumer)
    in Box (created by Flex)
    in Flex (created by ForwardRef)
    in ForwardRef
    in ForwardRef (created by ForwardRef)
    in ColorModeProvider (created by ForwardRef)
    in ThemeProvider (created by ThemeProvider)
    in ThemeProvider (created by ForwardRef)
    in ForwardRef (at pages/index.js:14)
    in main (at pages/index.js:13)
    in div (at pages/index.js:7)
    in Home (at _app.js:4)
    in MyApp
    in ErrorBoundary (created by ReactDevOverlay)
    in ReactDevOverlay (created by Container)
    in Container (created by AppContainer)
    in AppContainer
    in Root

in the console on the browser

kayleemchugh commented 3 years ago

I was having this issue when loading in a spinner from material-ui. The babel configurations above unfortunately didn't help me, so I tried a few different things.

I was able to resolve it by by lazy loading the component and setting ssr to false for the spinner.

import dynamic from 'next/dynamic' const LoadingSpinner = dynamic(() => import('./LoadingSpinner'), {ssr: false})

Not sure it'll be the right fit for all cases, but hope it helps someone!

Bonjur commented 3 years ago

Wrap your component with<NoSsr>

frontalicious-martijn commented 3 years ago

Looks like you need to add _document.js with a little bit of code to get Next.js and Styled Components to work together: https://styled-components.com/docs/advanced#nextjs

lazygagaliu commented 3 years ago

I used the 1.11.1 version and it doesn't work, and I go back to version 1.11.0-0 then it works with the settings that @bel7aG mentioned above.

samuelgoldenbaum commented 3 years ago

Fixed this by adding .babelrc file in root of the project and added::

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}
JPGallegos1 commented 3 years ago

hey all,

doing this will work:

Install babel plugin: yarn add --dev babel-plugin-styled-components

create new file .babelrc in your root project folder and add this:

{
    "env": {
      "development": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      },
      "production": {
        "plugins": [
          [
            "babel-plugin-styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
          ]
        ],
        "presets": ["next/babel"]
      }
    },
    "plugins": [
      [
        "babel-plugin-styled-components",
        { "ssr": true, "displayName": true, "preprocess": false }
      ]
    ]
}

If somebody is using Chakra UI and Emotion, this helps me.

omar-dulaimi commented 3 years ago

Unfortunately, no solutions here worked for me. This should be straightforward and properly documented.

AndresCampuzano commented 3 years ago

🚀I solved the issue using: .babelrc

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

XaFaK-01 commented 3 years ago

I just solved the issue by creating the "_document.js" and used the code as provided in the official example for Next.js from Material UI: Material UI Next.js Example

AndresCampuzano commented 3 years ago

🚀I solved the issue using: .babelrc

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

I'll leave my base Next template without the issue here: https://github.com/AndresCampuzano/Base-Next-js-React-Project

EdPutans commented 3 years ago

Copying this _document posted by songyule and wrapping the breaking Component in material's <NoSSr> helped me.

gnoyixiang commented 3 years ago

I have added the code in _document.js and .babelrc but I am still facing this error. When the app is first loaded, there is no error. But when I make a change in one of the files and refresh the page, the error is displayed.

Refer to https://github.com/gnoyixiang/next-standard-jester

I am using "styled-components": "5.2.0" and "babel-plugin-styled-components": "1.11.1"

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]],
  "env": {
    "production": {
      "plugins": [
        ["styled-components", { "ssr": true, "displayName": false, "preprocess": false }],
        ["transform-remove-console", { "exclude": ["error", "warn", "info"] }]
      ]
    }
  }
}

_document.js

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

async function configureStyledComponents (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()
  }
}

class MainDocument extends Document {}

MainDocument.getInitialProps = async ctx => {
  return await configureStyledComponents(ctx)
}

export default MainDocument
gnoyixiang commented 3 years ago

I have added the code in _document.js and .babelrc but I am still facing this error. When the app is first loaded, there is no error. But when I make a change in one of the files and refresh the page, the error is displayed.

Refer to https://github.com/gnoyixiang/next-standard-jester

I am using "styled-components": "5.2.0" and "babel-plugin-styled-components": "1.11.1"

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]],
  "env": {
    "production": {
      "plugins": [
        ["styled-components", { "ssr": true, "displayName": false, "preprocess": false }],
        ["transform-remove-console", { "exclude": ["error", "warn", "info"] }]
      ]
    }
  }
}

_document.js

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

async function configureStyledComponents (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()
  }
}

class MainDocument extends Document {}

MainDocument.getInitialProps = async ctx => {
  return await configureStyledComponents(ctx)
}

export default MainDocument

issue was resolved by removing "displayName": true in .babelrc

thexpand commented 3 years ago

What's the difference between using the custom _document.js and changing the .babelrc file?

kolnogorov commented 3 years ago

issue was resolved by removing "displayName": true in .babelrc

But what if i need to display class name?

jofelipe commented 3 years ago

For those who are having this error with use-dark-mode... Unfortunately I didn't find a solution, even with babel plugin, and styled components example.

The only solution I found to use dark mode with Next SSG without store any data on my server, was this one using CSS Variables by @hangindev (thank you)

I hope it helps someone :)

paulius1990 commented 3 years ago

@jofelipe Does issue resovled? None of this solutions worked for me, still errors appears after change.

jawadakram20 commented 3 years ago

No solution worked for me either.

zhangwei900808 commented 3 years ago

my sub component data passed in parent component getServerSideProps its workd!

parent

export async function getServerSideProps() {
  return {
    props: {
      randomValues: JSON.stringify(randomValues)

sub

<CalendarHeatmap
                weekdayLabels={weekcn}
                monthLabels={monthcn}
                startDate={shiftDate(today, -360)}
                endDate={today}
                values={JSON.parse(props.randomValues)}
                classForValue={value => {
                    if (!value) {
                        return 'color-empty';
                    }
                    return `color-gitlab-${value.count}`;
                }}
                showWeekdayLabels={true}
                onClick={value => alert(`Clicked on value with count: ${value.count}`)}
            />
MihaiWill commented 3 years ago

I added _document.js, .babelrc, dynamic import, still get the error: Warning: Prop 'style' did not match. Server:... and the component don't show up