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

Shivan M.

The Problem

How do I fix the “Hydration failed because the initial UI does not match what was rendered on the server” error with Next.js and React 18?

The Solution

This issue occurs because there is a mismatch between the React tree rendered during the first render in the browser (called hydration), and the React tree that was pre-rendered from the server.

Hydration is the process of React converting pre-rendered HTML into an interactive application by attaching event handlers. Hydration issues can be caused by several things:

  1. Using browser-only APIs in your rendering logic.
    • For example typeof window !== 'undefined or calls to localStorage.
  2. Using incorrect HTML tag nesting
    • Nesting interactive content inside other interactive content (e.g. a <button> nested in a <button> tag).
    • Nesting a <div> tag inside a <p> tag.
  3. Using browser extensions that modify the HTML content of a page.

There are a few solutions you can utilize to solve this error.

1. Check the Console For Errors About Improperly Nested HTML Tags

Your browser console window can give you more descriptive errors, pointing you to the issue causing the hydration failure. For example:

Warning: Expected server HTML to contain a matching <h1> in <p>. h1 p main div

You might have a component that includes a <div> tag that is nested inside a <p> tag in another component.

2. Disable SSR On Specific Components

Next.js allows you to disable SSR on particular components.

You can define a component with SSR disabled as follows:

const MyComponent = dynamic(() => import('../components/MyComponent'), { ssr: false })

If a component is not pre-rendered on the server, it will not cause a hydration mismatch error.

3. Explicitly Render Different Client-side Content

While you should ensure that a component renders the same content on the server and on the client to prevent hydration errors, you can render different client-side content during hydration by using useEffect.

Below, useEffect is used to toggle different content that is never pre-rendered by the server. This is because useEffect is called during hydration. This also means that you can use browser APIs like localStorage and window in the client-side-only content.

import { useState, useEffect } from 'react'; export default function App() { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); return ( <div> <h1> {isClient ? 'Never rendered on the server' : 'Prerendered on the server'} </h1> </div> ); }

4. Use suppressHydrationWarning

There are times when content will be different on the client and the server. In these situations, you can use the suppressHydrationWarning HTML attribute to silence the hydration mismatch caused by a component.

Get Started With Sentry

Get actionable, code-level insights to resolve Next.js performance bottlenecks and errors.

Run the line of code below to:

  1. Create a free Sentry account

  2. Run the CLI install command to automatically add the Sentry SDK to your project:

    npx @sentry/wizard@latest -i nextjs
  3. Start capturing errors and performance issues

Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

Share on Twitter
Bookmark this page
Ask a questionJoin the discussion

Related Answers

A better experience for your users. An easier life for your developers.

    TwitterGitHubDribbbleLinkedinDiscord
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.