vercel / next.js

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

React server mismatches: Prop `className` did not match. #11600

Closed voronianski closed 4 years ago

voronianski commented 4 years ago

Bug report

Describe the bug

After upgrading from Next.js 9.0.5 to 9.2.2 we noticed that we are getting server mismatches for a lot of our components which never errored before. We also tried other versions (e.g. 9.1.x, 9.2.x, 9.3.x) and all of them have the same problem.

To Reproduce

Please use this repository with easy reproducible error - https://github.com/voronianski/nextjs-server-mismatch-bug

The code of the example component is open-source UI library and you can find it here - https://github.com/sumup-oss/circuit-ui/blob/canary/src/components/Hamburger/Hamburger.js

Screenshots

image

mulholo commented 4 years ago

This sounds like an issue with emotion in your library to me.

Obviously it's a different library, but I know styled components recommend including styled-components as a peer dependency for UI libraries like the one you're using in this project.

Styled-components, also needs babel-plugin-styled-components and a modification of _document.tsx to ensure consistent hashing of classNames between environments. Is there something similar you need to do here?

Sorry that's not a solution but maybe some helpful notes.

lucent1090 commented 4 years ago

Hi @mulholio,

Thank you for the suggestion. I've tried the recommend from styled component's document in circuit-ui but the mismatch error still shows up.

And I think emotion natures comes with SSR setting. Shouldn't need more setup to make the hash consistency.

Please correct me if I miss anything here. Thanks!!

ghost commented 4 years ago

Hi @all, same problem on my site. Since 3 days i already stuck on this problem.

Packages

"next": "9.4.0", "@types/styled-components": "4.4.3", "babel-plugin-styled-components": "1.10.7", "styled-components": "4.4.1", ..

Node 12.14.1

I see that some guys had the same problems before (https://github.com/zeit/next.js/issues/3706) and so i tried to solve my problems with the tips there. Nothing worked for me :(

Fails

The errors occurs on dev env (yarn dev) in Chome dev console. If iam start my local prod env ( yarn build && yarn start )i see no error in Chrome dev console or server output log

barthicus commented 4 years ago

@kkis Try to upgrade next to 9.4.0 They fixed it already 💪

ghost commented 4 years ago

@barthicus Same prob

Bildschirmfoto 2020-05-13 um 12 43 31
barthicus commented 4 years ago

@kkis Can you provide some codesandbox os smth similar so we can see the problem and try to fix it? I'm not that familiar with next but I (or someone else here) can try to find a solution.

I'm using similar libs stack and this message is gone. My packages:

"dependencies": {
    "@material-ui/core": "^4.9.14",
    "@material-ui/icons": "^4.9.1",
    "date-fns": "^2.13.0",
    "firebase": "^7.14.3",
    "next": "9.4.0",
    "notistack": "^0.9.13",
    "react": "^16.13.0",
    "react-animations": "^1.0.0",
    "react-dom": "^16.13.0",
    "react-firebase-hooks": "^2.1.1",
    "react-firebaseui": "^4.1.0",
    "styled-components": "^5.0.0"
  },
  "devDependencies": {
    "@types/firebase": "^3.2.1",
    "@types/node": "13.13.5",
    "@types/react": "16.9.35",
    "@types/react-dom": "16.9.8",
    "@types/styled-components": "5.1.0",
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "babel-plugin-styled-components": "^1.10.0",
    "dotenv": "^8.2.0",
    "eslint": "^7.0.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-react": "^7.19.0",
    "eslint-plugin-react-hooks": "^4.0.1",
    "prettier": "^2.0.5",
    "typescript": "3.9.2"
  },

Ohh. Did you add this in _app.js/ts?

useEffect(() => {
    const jssStyles = document.querySelector('#jss-server-side')
    if (jssStyles && jssStyles.parentElement) {
      jssStyles.parentElement.removeChild(jssStyles)
    }
  }, [])
ghost commented 4 years ago

@barthicus I also saw the solution with the useEffect(). The problem ist, that i have no server rendered code with "#jss-server-side" inside that can be removed...

I will see that i can provide some code on codesandbox.

barthicus commented 4 years ago

@kkis Glad you made it! Although I think we shouldn't use these kind of things to get rid of error messages.

I'm pretty sure this can be fixed implementing some other changes in _app/_doc files but I'm not that experienced to be 100% sure.

Happy coding 👍

ghost commented 4 years ago

Hello, i still stuck on the problem, that in dev mode i see the error on initial page loading. On prod mode i don't see

 next": "9.4.0",
"react": "16.13.0",
"babel-plugin-styled-components": "1.10.7",
"styled-components": "4.4.1",
import ...

const AppWrapper: FC = (props) => {
  const { children } = props

  return (
    <ThemeProvider theme={getTheme()}>
      <MessageProvider>
        <Layout cmsContent={appData}>
          <LocationTracker>{children}</LocationTracker>
        </Layout>
      </MessageProvider>
    </ThemeProvider>
  )
}

class App extends NextApp<{
  apolloClients: ApolloClients
  statusCode?: number
}> {
  render() {
    const {
      apolloClients,
      Component,
      pageProps,
      statusCode,
    } = this.props

    return (
      <ApolloClientProvider clients={apolloClients}>
        <Component statusCode={statusCode} {...pageProps} />
      </ApolloClientProvider>
    )
  }
}
voronianski commented 4 years ago

@barthicus

@kkis Can you provide some codesandbox os smth similar so we can see the problem and try to fix it?

this repo with reproducible setup is available since bug is reported - https://github.com/voronianski/nextjs-server-mismatch-bug

I tried to upgrade to 9.4.0 but it didn't help.


What helped though is using completely ES5 transpiled version of the component - https://github.com/voronianski/nextjs-server-mismatch-bug/pull/1

Also using plain ESNext component fixes mismatches - https://github.com/voronianski/nextjs-server-mismatch-bug/pull/2

So something seems to be wrong with exported module versions of components - https://unpkg.com/@sumup/circuit-ui@1.8.0/lib/es/components/Hamburger/Hamburger.js

ghost commented 4 years ago

@voronianski

Here is the Codesandbox example. (https://codesandbox.io/s/next-typescript-app-f2k0y) (PS: The error does not appear every time in console)

index.tsx

import * as React from "react";
import styled from "../lib/styledComponents";

const Wrapper = styled.div`
  min-height: 100vh;
`;

export default function IndexPage() {
  return <Wrapper>WrapperContent2</Wrapper>;
}

lib/styledComponents.tsx

import * as styledComponents from "styled-components";
import { ThemedStyledComponentsModule } from "styled-components";

import { Theme } from "./defaultTheme";

const {
  default: styled,
  css,
  createGlobalStyle,
  ThemeProvider,
  ThemeConsumer,
  keyframes
} = (styledComponents as any) as ThemedStyledComponentsModule<Theme>;

export {
  css,
  createGlobalStyle,
  keyframes,
  ThemeProvider,
  ThemeConsumer,
  Theme
};

export default styled;

lib/defaultTheme.tsx

export const defaultTheme = {
  backgroundColor: "#ffffff",
  borderRadius: "5px",
  breakpoints: ["576px", "768px", "992px"],
  color: "#666666"
};

export type Theme = Readonly<typeof defaultTheme>;
export const Theme = defaultTheme;
export default defaultTheme as Theme;

You can see that the error appear when i use custom theming. I would be really appreciate if someone knows how to solve the problem.

UPDATE What fixed the problem ? Don't import styled from custom theme!

Create a file styled.d.ts

import {} from 'styled-components'
import { theme } from './utils/theme'

declare module 'styled-components' {
  type Theme = typeof theme
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  export interface DefaultTheme extends Theme {}
}

and import styled from styled-components in your components

aomini commented 4 years ago

This appears for me as well. I've used the _document.js from next examples as well as updated babel rc. Next version is 9.4.0

KyorCode commented 4 years ago

Same problem here, trying to use styled(ExternalComponent) mismatches classes. Next version 9.4.4 Styled-components version 5.1.1 babel-plugin-styled-components version 1.10.7

jeffscottward commented 4 years ago

I am using 9.50 and ThemeUI and am also getting this.

No matter how many elements I remove -(as long as there is even just one element in the tree) - I get the error.

What is strange is that this error doesn't show up in Blink based browsers but does show up everywhere else like Safari, Firefox, etc

ThemeUI sits ontop of Emotion - could be an Emotion problem too. Just adding my experience here

Screen Shot 2020-07-30 at 2 17 29 PM
jflayhart commented 4 years ago

Same problem here, trying to use styled(ExternalComponent) mismatches classes.

Similar issue and @KyorCode's comment was my problem. I just had to convert all const StyledComponent = styled(Component) to be const StyledComponent = styled.[html-element-goes-here]... for each "offending" component.

Total speculation, but maybe it's that the server and client can't rectify some type of ambiguity with styled(Component), which is made to inherit classes of another styled component.

kolnogorov commented 4 years ago

9.5.2, bug is still present

serkanz commented 4 years ago

Also 9.5.3 has the same bug

doptster commented 4 years ago

9.5.5, bug still persist, it doesn't affect the application much but the client side always fire this warning.

LuizHAP commented 4 years ago

Version 10 and the problem still persists

gabsn commented 4 years ago

I can confirm that with next 10 😢

siulca commented 4 years ago

This has been reported in April and still no fix in November?!

timneutkens commented 4 years ago

This has been reported in April and still no fix in November?!

This is not a bug in Next.js. You're likely using a css-in-js library that is not pre-rendering styles correctly (or not pre-rendering at all) which causes a hydration mismatch given the pre-rendered markup would not match the markup generated client-side.

altschuler commented 4 years ago

For JSS this fixed it in my case https://medium.com/wesionary-team/implementing-react-jss-on-next-js-projects-7ceaee985cad

Timer commented 4 years ago

Closing as it's a bug in your application and can be better solved in Discussions or on Discord!

msreekm commented 4 years ago

for anyone still getting this error with Material-ui and styled components ,I have working code here- https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate

make sure to include the flush() https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/3a33ef36d7a956e7da357ca9d02333ee43d72979/pages/_document.js#L27

mysticaltech commented 4 years ago

Hey folks, in my case it was the reactStrictMode: true flag in next.conf.js that was causing the issue, when I removed it, it's gone! @Timer there is probably a bug here.

timneutkens commented 4 years ago

Hey folks, in my case it was the reactStrictMode: true flag in next.conf.js that was causing the issue, when I removed it, it's gone! @Timer there is probably a bug here.

It's more likely you're using a library that is not strict mode compatible as strict mode re-executes renders multiple times to check for concurrent mode compatibility.

mysticaltech commented 4 years ago

@timneutkens You are right I'm using plotly.js that is probably not strict mode compatible. So something like this could cause the client to render something and the server something else. I just don't understand. In my case the class names were different. Server: Mui-xyz-26, Client: Mui-xyz-27.

christoffee commented 3 years ago

This is not a bug in Next.js. You're likely using a css-in-js library that is not pre-rendering styles correctly (or not pre-rendering at all) which causes a hydration mismatch given the pre-rendered markup would not match the markup generated client-side.

How are component libraries, using styled components, meant to pre-render styles? Our set up is we have a component library using the babel-plugin-styled-components ( ['styled-components', { ssr: true, displayName:true }] )... and the same within the nextjs app... but we still get that mismatch classname warning.

"styled-components": "^5.2.0" "babel-plugin-styled-components": "^1.10.6" "next": "10.0.1"

timneutkens commented 3 years ago

This is not a bug in Next.js. You're likely using a css-in-js library that is not pre-rendering styles correctly (or not pre-rendering at all) which causes a hydration mismatch given the pre-rendered markup would not match the markup generated client-side.

How are component libraries, using styled components, meant to pre-render styles? Our set up is we have a component library using the babel-plugin-styled-components ( ['styled-components', { ssr: true, displayName:true }] )... and the same within the nextjs app... but we still get that mismatch classname warning.

"styled-components": "^5.2.0" "babel-plugin-styled-components": "^1.10.6" "next": "10.0.1"

Make sure you set up pages/_document to pre-render the styled-components styles: https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js

fraanmarelli commented 3 years ago

for anyone still getting this error with Material-ui and styled components ,I have working code here- https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate

make sure to include the flush() https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/3a33ef36d7a956e7da357ca9d02333ee43d72979/pages/_document.js#L27

this worked for me today :)

machineghost commented 3 years ago

Make sure you set up pages/_document to pre-render the styled-components styles:

I have tried using both a custom _document.js of https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js, and the one from step 6 of this article: https://dev.to/aprietof/nextjs--styled-components-the-really-simple-guide----101c

Neither one fixes the warning :(

P.S. I do have the babel plugin installed, and I've tried umpteen different variations of the .babelrc file, all to no avail.

raptoria commented 3 years ago

+1

jessetinell commented 3 years ago

I've ended up here for 3 different projects the past couple of months. This is what has silenced the error all 3 times:

  1. Create the .babelrc file in your root folder
  2. Add this: { "presets": [ "next/babel" ], "plugins": [ [ "styled-components", { "ssr": true } ] ] }

(hello to future me for the 4th project)

olarra commented 3 years ago

It was driving me crazy! I spent so many days in this warning and no of the solutions fixed it for me. I finally getting work putting this in the .babelrc file


{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "ssr": true,
        "minify": true,
        "transpileTemplateLiterals": true,
        "pure": true,
        "displayName": true,
        "preprocess": false
      }
    ]
  ]
 }
tlkahn commented 3 years ago

Confirmed it works, at least for me.

I finally getting work putting this in the .babelrc file

{
 "presets": [
   "next/babel"
 ],
 "plugins": [
   [
     "babel-plugin-styled-components",
     {
       "ssr": true,
       "minify": true,
       "transpileTemplateLiterals": true,
       "pure": true,
       "displayName": true,
       "preprocess": false
     }
   ]
 ]
}
norbertbiro commented 3 years ago

It was driving me crazy! I spent so many days in this warning and no of the solutions fixed it for me. I finally getting work putting this in the .babelrc file

{
 "presets": [
   "next/babel"
 ],
 "plugins": [
   [
     "babel-plugin-styled-components",
     {
       "ssr": true,
       "minify": true,
       "transpileTemplateLiterals": true,
       "pure": true,
       "displayName": true,
       "preprocess": false
     }
   ]
 ]
}

I can also confirm that it works for me as well!

xasopheno commented 3 years ago

Yes. That works for me as well. Thank you.

amponsah commented 3 years ago

I'm not using style components and still have this issue! I'm using Ant design, anyone else has this problem with ant design?

maksym3d commented 3 years ago

For what it's worth, setting the attribute programmatically seems to have cleared the issue in FF:

<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>

became this:

<button onClick={() => gotoPage(0)} {...({disabled:!canPreviousPage})}>

AeShevch commented 3 years ago

For what it's worth, setting the attribute programmatically seems to have cleared the issue in FF:

<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>

became this:

<button onClick={() => gotoPage(0)} {...({disabled:!canPreviousPage})}>

Did you manage to solve the problem? I also use antd

maksym3d commented 3 years ago

For what it's worth, setting the attribute programmatically seems to have cleared the issue in FF: <button onClick={() => gotoPage(0)} disabled={!canPreviousPage}> became this: <button onClick={() => gotoPage(0)} {...({disabled:!canPreviousPage})}>

Did you manage to solve the problem? I also use antd

The code above did fix it for me, although I also did add babel and made changes to the _document (https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/3a33ef36d7a956e7da357ca9d02333ee43d72979/pages/_document.js#L27) as described in the discussion above.

clementohNZ commented 3 years ago

If you're using material UI, this is a great guide I found with explanations on why server-side styles need to be removed and how to do it.

After following this guide I never saw the issue again!

Xin2050 commented 3 years ago

I've ended up here for 3 different projects the past couple of months. This is what has silenced the error all 3 times:

  1. Create the .babelrc file in your root folder
  2. Add this: { "presets": [ "next/babel" ], "plugins": [ [ "styled-components", { "ssr": true } ] ] }

(hello to future me for the 4th project)

This is total works for me, Thanks a lot!

amponsah commented 3 years ago

@globalblob

Using AntDesign: The material ui link did not help me. Don't know it its works for styled-components!

The only way I managed to make it work was to wrap my component in next/dynamic. After this all my className mismatched disappeared.

`import dynamic from "next/dynamic";

const Hosting = dynamic(() => import("./Hosting"), { ssr: false, });

export default function HostingPage() { return } `

sheeraz1022 commented 3 years ago

Hi Guys,

I am facing the same issue using NextJS along with Styled Components. Following these steps has worked for me when I am starting the dev server. But once I change any code and refresh the page, again I get the same error.

Has anyone encountered a similar issue?

JayBee007 commented 3 years ago

@sheeraz1022 Yes.

  1. Starting the dev server, there is no error
  2. Change the props to style-components so new class is applied, gives an error about className mismatch on client and server
  3. Further restarting of dev server doesnt solve the issue
  4. And then again once in a while, the cycle repeats from point 1

But I have a monorepo, and am building styled-components using tsdx and providing custom .babelrc

WebAiz commented 3 years ago

I had similar issue when server and client classNames differed with extra "logged" string, so dynamic import resolved the issue. Hope this helps

AndrewMyint commented 3 years ago

It was driving me crazy! I spent so many days in this warning and no of the solutions fixed it for me. I finally getting work putting this in the .babelrc file

{
 "presets": [
   "next/babel"
 ],
 "plugins": [
   [
     "babel-plugin-styled-components",
     {
       "ssr": true,
       "minify": true,
       "transpileTemplateLiterals": true,
       "pure": true,
       "displayName": true,
       "preprocess": false
     }
   ]
 ]
}

This works for me as well, after deleting my .next folder.

DevDaveJ commented 3 years ago

If you're using material UI, this is a great guide I found with explanations on why server-side styles need to be removed and how to do it.

After following this guide I never saw the issue again!

Im using nextjs + material-ui. Not using typescript but my _document.js and _app.js are similar if not the same. The issue still occurs, but what worked for me was changing the import of the component causing the issue.

From: import { Box } from '@material-ui/core';

To: import Box from '@material-ui/core/Box';