Fix the React 18: Hydration failed because the initial UI does not match error
Although server side rendering is already available in React 16.8, Automatic hydration will be introduced in React 18. This is the reason why in new React, Next.js projects often show the following error message on the console:
...
Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.
What is hydration
The hydration process is an important part of using server side rendering. Hydration is the process of converting static HTML into a fully interactive React application by attaching event handlers to the DOM elements. This is done when a React application is rendered on the server and then the HTML is sent to the client. When the HTML arrives on the client, React hydrates it by attaching event handlers to the DOM elements so that the user can interact with the application.
The main problem
The error Hydration error occurs when the initial UI rendered on the server does not match the UI rendered on the client after hydration. The most common reasons are:
- Incorrect HTML. For example a
div
tag inside ap
tag, or atr
outside oftbody
. - Rendering based on client side properties. For example an if statement based on
window
object. - Browser extensions that modify the HTML code. Such as LastPass or Grammarly.
Fix HTML errors
The first step is to check that the HTML code is valid. If you get the error Hydration failed because of an HTML error, you will find validateDOMNesting
warnings in the error messages that appear on the console. For example:
or
These mistakes are definitely worth correcting.
Fix Hydration error with useEffect
If you don't need server side rendering, you can work around the error with the useEffect
hook. The hook can be used to update the component's state on the client after the component has been hydrated. This will ensure that the component renders the same content server-side and client-side.
For example:
"use client"
import Home from '@/components/Home';
import { useEffect, useState } from 'react';
export default function HomePage() {
const [firstRender, setFirstRender] = useState(true);
useEffect(()=>{
setFirstRender(false);
},[]);
if (firstRender) {
return <></>
}
return <Home />
}
The first line is important for Next.js. Since useEffect
is only used for client components and by default all components are server components in Next.js, you need to specifically mark that this is a client component using the "use client"
.
Fix by disabling SSR
For Next.js projects, you can also use dynamic import, where you explicitly define that the component should not use server side rendering. You can use the dynamic
function from the next/dynamic
library.
For example you can wrap your component like this:
import dynamic from 'next/dynamic'
const TestPageWithoutSSR = dynamic(() => import('./TestPage'), {
ssr: false
})
export default () => <TestPageWithoutSSR />
Surpress Hydration failed error
As a last resort, you can try to suppress the error. The suppressHydrationWarning
prop can be used to suppress the hydration warning that is emitted by React when the initial UI rendered on the server does not match the UI rendered on the client after hydration.
Important:
- This does not solve the problem, it just hides it.
- At the time of writing the property is not working properly due to a bug, so in many cases it has no effect.
References