Fix React hydration errors
Hydration errors mean the server-rendered HTML did not match the first client render. The fix is to find the source of nondeterminism — dates, random values, browser-only APIs, or invalid HTML nesting.
WorkflowDifficulty: moderatemedium risk
Last verified · Updated May 22, 2026
A hydration error means the HTML React rendered on the server did not match the first client render. Track down the nondeterministic value or invalid nesting causing the mismatch — do not silence it by disabling SSR.
Symptoms
- "Hydration failed because the server rendered HTML didn't match the client."
- Text content or attributes flicker on first paint.
- Errors that only appear in production SSR builds.
Likely causes
- Rendering Date.now()/new Date()/Math.random() during render.
- Reading window/localStorage during the initial render.
- Invalid HTML nesting (e.g. <div> inside <p>).
- Locale- or timezone-dependent formatting differing between server and client.
Diagnostic commands
shell
# Reproduce with a production-like SSR build$ npm run build && npm run start# Then open the page and read the first hydration warning's component stackTest failure debuggingAI debugging prompt
I'm getting a React hydration mismatch on <route>. Here is the warning and component stack: <paste>. Inspect the named component and its children for nondeterministic render values (dates, random, window/localStorage) and invalid HTML nesting. Propose the smallest change that makes server and client render identically — prefer useEffect or suppressHydrationWarning only as a last resort, and explain the tradeoff.
Safety: Do not disable SSR or wrap large trees in suppressHydrationWarning to hide the real cause.
Safe fix workflow
- Move nondeterministic values into useEffect so they only run on the client.
- Guard browser-only APIs behind a mounted check.
- Fix invalid HTML nesting flagged by the warning.
- Re-run the production SSR build and confirm the warning is gone.
Escalation checklist
- Mismatch persists after removing obvious nondeterminism
- A third-party component renders differently across environments
- The mismatch only reproduces under a specific locale/timezone
Related upgrade pages
- Migrate AngularJS to Reacthigh riskEarlier step in the upgrade chain
- Migrate React Class Components to Hookslow riskNext step forward
- React 16 to React 19 Migration Guidehigh riskRelated path
- React 17 to React 19 Migration Guidehigh riskRelated path
- React 18 to React 19 Migration Guidemedium riskRelated path
- Upgrade to React 19medium riskNext step forward
Frequently asked questions
Is suppressHydrationWarning a real fix?
Only for intentionally dynamic content like timestamps on a single element. Using it to mask a structural mismatch hides bugs that will resurface.