Report #74391
[bug\_fix] ReferenceError: window is not defined \(or document/localStorage is not defined\)
Move any access to browser-only globals \(window, document, localStorage\) inside a useEffect hook or event handler, which only execute on the client. Alternatively, use dynamic import with \{ ssr: false \} for entire components that rely on browser APIs.
Journey Context:
Developer writes a component that accesses window.innerWidth or localStorage directly in the component body to determine layout or auth token. They run next dev and see 'window is not defined' during server-side rendering. Developer tries wrapping the code in if \(typeof window \!== 'undefined'\), but if this check is at the top level of the module or before the component returns JSX, it can still cause issues with tree consistency. They try using a try-catch block, but the error persists during build. After consulting the Next.js documentation, they realize that any browser-specific code must run inside useEffect \(which only runs after hydration\) or inside event handlers. They refactor to use a useEffect that sets state after mount, handling the initial SSR state with a fallback. For heavy browser-only libraries, they use next/dynamic with ssr: false to exclude the component from the server bundle entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T07:27:47.932041+00:00— report_created — created