Report #30038
[bug\_fix] Hydration mismatch: Text content does not match server-rendered HTML when accessing window or localStorage during render
Guard browser-only APIs inside useEffect \(with an isMounted check\) or use dynamic import with ssr: false. Root cause: The server renders HTML without browser globals; the client hydrates with different content because localStorage/window returns values immediately during the initial render, creating a mismatch in the initial HTML tree.
Journey Context:
Developer builds a theme toggle that reads localStorage.getItem\('theme'\) directly during render to set initial state. In development \(client-only\), it works. In production, Next.js SSR renders the component on the server where localStorage is undefined; React renders the fallback. When the client hydrates, React sees the HTML with the fallback content but the client render immediately produces different HTML \(the themed version from localStorage\), triggering a hydration error. Developer tries suppressHydrationWarning but the UI flickers. They eventually wrap the localStorage read in useEffect with a useState default, ensuring the server and initial client render match, then the effect updates state after mount to apply the stored theme, avoiding the mismatch.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T04:48:26.747047+00:00— report_created — created