On this page
Hydration attaches React behavior to HTML that already exists. The first browser render must describe the same initial interface as the server render. A mismatch means those two descriptions disagree. Refreshing until the warning disappears does not repair the contract; it only changes the conditions that exposed it.
Compare the two initial snapshots
Begin with the exact component named in the warning and identify every input used during its first render. Look for time, randomness, locale, browser storage, cookies, request-specific data, and conditional environment checks. Initial agreement matters more than whether both renders eventually reach the same state.
Paste sanitized server and browser payloads into the JSON Formatter to compare their structures and values. Confirm that both renders received the same identifier and flags. Formatting is especially useful when one path silently omits a property that another path defaults differently.
Separate hydration mismatches from later state changes. Updating a greeting after an effect reads browser preferences can be legitimate. Rendering a different greeting immediately because window exists in the browser creates disagreement before hydration has completed. The distinction is about timing, not whether the final greeting is desirable.
Remove nondeterminism from render
Date.now and Math.random are common offenders. Calling either during server render and again during browser render produces independent values. Supply an initial value from the server when it is part of the document, or initialize browser-only behavior after hydration when that is genuinely required.
Locale formatting can also vary by environment. A date rendered with the server's default time zone may differ from the user's browser. Choose a consistent initial format and time zone, then optionally enhance the display after hydration. Deterministic rendering makes behavior testable as well as hydration-safe.
'use client';
import { useEffect, useState } from 'react';
export function LocalTime({ iso }: { iso: string }) {
const [display, setDisplay] = useState(iso);
useEffect(() => {
setDisplay(new Intl.DateTimeFormat(undefined, {
dateStyle: 'medium',
timeStyle: 'short',
}).format(new Date(iso)));
}, [iso]);
return <time dateTime={iso}>{display}</time>;
}This component initially renders the same ISO value on both sides. It then enhances the presentation using the browser's locale. The input must still be a valid date string, and the layout should tolerate the display changing width. This is a deliberate two-phase presentation, not a reason to defer all page content.
Consult the React hydrateRoot reference for the expected contract. React's recovery behavior should not be treated as a substitute for correct markup; mismatches can undermine event attachment and force recovery work.
Check markup and browser parsing
The browser parses HTML before React hydrates it. Invalid nesting may be repaired into a different DOM tree than your JSX suggests. A paragraph containing block-level structures or a nested interactive element can therefore create a mismatch even when the source looks identical on both sides.
Inspect the actual DOM and compare it with the response source. Parser repair is easy to miss when inspecting JSX alone. Look at table structures, paragraphs, buttons, anchors, and third-party components that choose their own wrapper elements. A design-system component named Text might render a paragraph rather than a neutral span.
Use the MDN HTML reference to verify content models instead of rearranging elements until the warning disappears. Prefer semantic corrections that preserve interaction behavior. Replacing everything with div elements may hide one nesting issue while weakening the document's structure.
Also test without extensions that modify the page. Password managers, translation tools, and injected browser UI can change markup before hydration. That does not mean every mismatch should be blamed on extensions; first reproduce in a clean profile and compare the result with the normal environment.
Handle browser-only state deliberately
Reading localStorage during render can make the client start from a different state than the server. For a theme or preference, decide whether the server can know the value through a cookie. If not, choose a stable initial state and an explicit enhancement strategy that accepts any visual transition.
Do not use typeof window as a blanket branch inside render to produce unrelated initial trees. The check avoids a reference error but can create the mismatch itself. Browser availability and first-render consistency are separate requirements.
For components that genuinely cannot render meaningfully on the server, use the framework's documented client-only loading pattern at an appropriate boundary. Keep that exception narrow. Turning the whole route into client-only rendering to silence one widget loses server-rendering benefits and makes diagnosis harder.
The Next.js hydration error guide explains supported escape hatches. suppressHydrationWarning is intended for limited unavoidable differences, not a general repair switch. It does not establish a correct data contract, sanitize markup, or guarantee React will patch every mismatch the way you expect.
Reproduce the conditions that caused it
Test a hard refresh, not only client-side navigation. Hydration is particularly visible on initial document loads, while later transitions can follow a different path. Try multiple locales and time zones when dates or numbers are involved. Include an authenticated and signed-out request if personalization affects the first render.
Capture server props and the first client props in a minimal reproduction. Remove unrelated widgets until the warning disappears, then restore them one at a time. Small reproductions expose hidden environment reads and wrapper changes faster than changing a global rendering setting.
Add a regression test for the actual source of nondeterminism. Fix the clock for time-sensitive output, provide a stable locale, and supply the same initial snapshot to server and browser rendering. A snapshot test of the final hydrated UI alone can miss the initial disagreement entirely.
The React collection and development collection contain related implementation patterns. Keep your own hydration checklist focused on concrete evidence: incoming data, parsed DOM, first-render values, and environment differences. Evidence before suppression prevents an intermittent warning from becoming an undocumented production assumption.
Finally, confirm that the fix preserves useful initial content. A page that renders nothing until an effect runs may avoid disagreement, but it can also obscure the original rendering design problem. Prefer shared inputs and deterministic output whenever possible.
Key takeaways
- Compare server output with the first browser render, not merely the final UI.
- Stabilize time, randomness, locale, initial data, and browser preference handling.
- Check parsed HTML and third-party wrappers before using narrowly scoped escape hatches.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor