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

Total
0
Shares

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


Solution

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.

_x000D_

_x000D_

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>
  )
}

_x000D_

_x000D_

_x000D_

Source: StackOverflow.com

Leave a Reply

Your email address will not be published. Required fields are marked *