How to fix hydration error: Text content does not match in Next.js

My Next.js app crashes on load with one of these errors:

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

or

Warning: Text content did not match. Server: "..." Client: "..."

The page shows a blank screen or flickering content. What causes this and how do I fix it?

Solution

Hydration errors happen when a component renders differently on the server and the client. The most common cause is reading browser-only values (window, localStorage, navigator, Date.now()) directly during render.

Move those reads into a useEffect so they only run on the client after hydration:

'use client'

import { useState, useEffect } from 'react'

export default function UserGreeting() {
  const [name, setName] = useState('')

  useEffect(() => {
    setName(localStorage.getItem('username') ?? '')
  }, [])

  return <p>Hello, {name || 'stranger'}</p>
}

If the mismatch is intentional (e.g. a timestamp that differs by a few milliseconds), you can suppress the warning on a specific element:

<time suppressHydrationWarning>{new Date().toLocaleTimeString()}</time>
Alternative #1

If the mismatch comes from a third-party package or a component you do not control, you can defer rendering it entirely until after hydration using a mounted state guard:

'use client'

import { useState, useEffect } from 'react'
import ClientOnlyWidget from 'some-library'

export default function Page() {
  const [mounted, setMounted] = useState(false)

  useEffect(() => {
    setMounted(true)
  }, [])

  if (!mounted) return null

  return <ClientOnlyWidget />
}

This prevents the component from rendering on the server at all, so there is no mismatch to cause an error.

Alternative #2

Browser extensions like password managers, ad blockers, or translation tools can inject extra DOM nodes that React did not expect. To confirm this is the cause, open an incognito window with no extensions and check if the error disappears.

If extensions are responsible, there is nothing to fix in your code. The suppressHydrationWarning prop on the body element is the accepted workaround:

// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body suppressHydrationWarning>{children}</body>
    </html>
  )
}

This tells React to ignore mismatches on that element and its direct children.

Alternative #3

A common source of hydration errors in Next.js is conditional rendering based on screen size using JavaScript. Server-side there is no screen, so the condition evaluates differently.

Instead of JavaScript-based media queries, use CSS to show and hide elements. This way the HTML is identical on server and client:

// Instead of this (causes hydration error):
const isMobile = window.innerWidth < 768
return isMobile ? <MobileNav /> : <DesktopNav />

// Do this instead:
return (
  <>
    <MobileNav className="block md:hidden" />
    <DesktopNav className="hidden md:block" />
  </>
)
Last modified: April 16, 2026
Stay in the loop
Subscribe to our newsletter to get the latest articles delivered to your inbox