Report #91337
[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 logic that accesses browser-only APIs \(window, localStorage, document, Math.random, Date.now\) into a useEffect hook, which only runs client-side after hydration. Alternatively, add the \`suppressHydrationWarning\` prop to the element for unavoidable mismatches \(like timestamps\). Root cause: The server renders HTML without browser APIs; React expects the initial client render to match this markup exactly before hydrating.
Journey Context:
A developer adds \`const id = Math.random\(\)\` or \`const theme = localStorage.getItem\('theme'\)\` at the top level of a component. In development with Fast Refresh, it appears to work, but a hard refresh throws a red error overlay: "Text content does not match server-rendered HTML." The developer checks the Network tab—the API data is correct. They suspect a React version mismatch and upgrade Next.js. The error persists. They add console.logs and realize the server HTML contains a different random ID or "undefined" compared to the client. They learn that \`useEffect\` runs only after mounting, so moving the logic there ensures the initial server/client HTML matches, allowing React to hydrate successfully.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T11:54:10.534571+00:00— report_created — created