React 18: Hydration failed because the initial UI does not match what was rendered on the server

12,970

Solution 1

I have been experiencing the same problem lately with NextJS and i am not sure if my observations are applicable to other libraries. I had been wrapping my components with an improper tag that is, NextJS is not comfortable having a p tag wrapping your divs, sections etc so it will yell "Hydration failed because the initial UI does not match what was rendered on the server". So I solved this problem by examining how my elements were wrapping each other. With material UI you would need to be cautious for example if you use a Typography component as a wrapper, the default value of the component prop is "p" so you will experience the error if you don't change the component value to something semantic. So in my own opinion based on my personal experience the problem is caused by improper arrangement of html elements and to solve the problem in the context of NextJS one will have to reevaluate how they are arranging their html element.

import Image from 'next/image'
/**
 * This might give that error
 */
export const IncorrectComponent = ()=>{
  return(
    <p>
      <div>This is not correct and should never be done because the p tag has been abused</div>
      <Image src='/vercel.svg' alt='' width='30' height='30'/>
    </p>
  )
}

/**
 * This will work
 */
export const CorrectComponent = ()=>{
  return(
    <div>
      <div>This is correct and should work because a div is really good for this task.</div>
      <Image src='/vercel.svg' alt='' width='30' height='30'/>
    </div>
  )
}

Solution 2

This solution work for me:

export default function MyApp({ Component, pageProps }: AppProps) {
  const [showChild, setShowChild] = useState(false);
  useEffect(() => {
    setShowChild(true);
  }, []);

  if (!showChild) {
    return null;
  }

  if (typeof window === 'undefined') {
    return <></>;
  } else {
    return (
      <Provider store={store}>
        <Component {...pageProps} />
      </Provider>
    );
  }
}

I also using NextJS, Redux Toolkit

Solution 3

Removing the <p> tag solved my similar problem with NEXTJS..

Share:
12,970
auser
Author by

auser

Updated on June 13, 2022

Comments

  • auser
    auser almost 2 years

    I'm trying to get SSR working in my app but I get the error:

    Hydration failed because the initial UI does not match what was rendered on the server.

    Live demo code is here

    Live demo of problem is here (open dev tools console to see the errors):

    // App.js

     import React from "react";
        
      class App extends React.Component {
    
      head() {
        return (
          <head>
            <meta charSet="utf-8" />
            <meta
              name="viewport"
              content="width=device-width, initial-scale=1, shrink-to-fit=no"
            />
            <meta name="theme-color" content="#000000" />
            <title>React App</title>
          </head>
        );
      }
    
      body() {
        return (
          <body>
            <div className="App">
              <h1>Client says Hello World</h1>
            </div>
          </body>
        );
      }
    
      render() {
        return (
          <React.Fragment>
            {this.head()}
            {this.body()}
          </React.Fragment>
        )
      }
    }
    export default App;
    

    // index.js

    import React from "react";
    import * as ReactDOM from "react-dom/client";
    import { StrictMode } from "react";
    
    import App from "./App";
    
    
    // const container = document.getElementById("root");
    const container = document.getElementsByTagName("html")[0]
    
    ReactDOM.hydrateRoot(
      container,
      <StrictMode>
        <App />
      </StrictMode>
    );
    

    The Html template shown in the live demo is served by the backend and generated using the following code:

    const ReactDOMServer = require('react-dom/server');
    
    const clientHtml = ReactDOMServer.renderToString(
    <StrictMode>
        <App />
    </StrictMode>
    )
    

    // serve clientHtml to client

    I need to dynamically generate <head></head> and <body></body> section as shown in the App class

  • Admin
    Admin about 2 years
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
  • Admin
    Admin about 2 years
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
  • user3174311
    user3174311 about 2 years
    I am facing the same problem, using next-auth, the line triggering that error is const {data: session} = useSession(); any idea how could I fix it?
  • Daniel
    Daniel about 2 years
    lul, this fixed my problem. I had <hr /> as a child of <p> thanks for being a beast @Motsi +1
  • Liki Crus
    Liki Crus almost 2 years
    I don't think this does make sense.
  • webHasan
    webHasan almost 2 years
    @user3174311 for next auth if you use code like this produce the error if(typeof window !== "undefined" && loading) { return null; } You can change it as if(typeof window === "undefined" || loading) { return null; }
  • Rob
    Rob almost 2 years
    I'm using Sanity as my CMS, and I had the <BlockContent ... /> component wrapped in a <p> tag. Removing the <p> tag fixed my issue. Thanks!
  • Digamber negi
    Digamber negi almost 2 years
    it's probably due to the wrong way of using <HTML> tags in Nextjs. For me it was just too many <section> inside a <main>
  • Harry Theo
    Harry Theo almost 2 years
    For me it was a <footer> element inside <div id="_next">. Moved the footer element in _document.jsx as a child of <body> to fix it.
  • Ian Sebastian
    Ian Sebastian almost 2 years
    Holly molly, thanks
  • boyenec
    boyenec almost 2 years
    Thanks man. I was facing the same issue. I was warping div element inside an paragraph like this <p><div dangerouslySetInnerHTML={{ __html: data),}}/></p> which nextjs not allow and throwing hydration failed error