Report #100088
[bug\_fix] Hydration failed because the initial UI does not match what was rendered on the server \(Text content does not match server-rendered HTML\)
Move any browser-only logic \(window, localStorage, Date.now, Math.random\) into a useEffect that runs after hydration, so the initial server render and the first client render produce identical HTML. For components that can never render on the server, import them with next/dynamic and \{ ssr: false \}. For unavoidable one-level mismatches such as timestamps, add suppressHydrationWarning=\{true\} to the element.
Journey Context:
A page shows a greeting based on localStorage.getItem\('name'\). In dev it seems fine, but on hard refresh Next.js throws a hydration error. The server prerenders with no name \(localStorage does not exist on the server\), while the client first render reads the stored name and produces different text. React then compares the server HTML to the client tree and aborts hydration. Wrapping the localStorage read in useEffect with an empty dependency array delays the read until after hydration, so the initial client render matches the server. Alternatively, dynamic import with ssr: false skips server rendering entirely for that subtree. The suppressHydrationWarning escape hatch is only for text that is allowed to differ and only works one level deep.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-01T04:37:55.218120+00:00— report_created — created