- Published on
Fixing 'Window is Not Defined' Error in Next.js
- Authors
- Name
- Ripal & Zalak
Fixing 'Window is Not Defined' Error in Next.js
When working with Next.js, a common error developers encounter is:
Unhandled Rejection (ReferenceError): window is not defined
This error occurs because Next.js executes code on the server side before rendering it on the client side. The window object is specific to browsers and doesn't exist in the Node.js environment where the server-side rendering (SSR) occurs.
Why Does This Happen?
Next.js is a universal framework that renders JavaScript both on the server and the client. When code references window during server-side rendering, it throws an error because the server has no concept of browser-specific objects like window or document.
Common Scenarios
- Accessing
windowin React lifecycle methods likecomponentWillMount. - Using libraries that directly access
window. - Inline scripts or dynamic rendering that rely on
window.
How to Fix 'Window is Not Defined'
Here are the best solutions to resolve this issue:
1. Check for window Safely
Wrap the code using typeof window to ensure it's only executed on the client:
if (typeof window !== 'undefined') {
console.log('Client-side code execution')
}
2. Use useEffect in Functional Components
In functional components, ensure browser-specific code runs only after the component mounts:
import React, { useEffect } from 'react'
const MyComponent = () => {
useEffect(() => {
console.log(window.innerWidth)
}, [])
return <div>Client-side component</div>
}
3. Use componentDidMount in Class Components
In class components, move window-dependent code to componentDidMount:
class MyComponent extends React.Component {
componentDidMount() {
console.log(window.innerWidth)
}
render() {
return <div>Class component example</div>
}
}
4. Dynamic Import with No SSR
For components or libraries that depend on window, use Next.js's dynamic import with ssr: false:
import dynamic from 'next/dynamic'
const NoSSRComponent = dynamic(() => import('../components/SomeComponent'), { ssr: false })
const Page = () => (
<div>
<NoSSRComponent />
</div>
)
export default Page
5. Custom Hook for Client-Side Code
Create a custom hook for client-side rendering logic:
import { useState, useEffect } from 'react'
const useIsClient = () => {
const [isClient, setIsClient] = useState(false)
useEffect(() => {
setIsClient(true)
}, [])
return isClient
}
const MyComponent = () => {
const isClient = useIsClient()
if (!isClient) return null
return <div>Client-side rendering enabled</div>
}
6. Avoid Using window Altogether
Whenever possible, use libraries or APIs that support server-side rendering without relying on browser-specific objects.
Best Practices to Avoid window Errors
- Always Check for Environment: Use
typeof window !== 'undefined'before accessing browser-specific objects. - Use Next.js Features: Leverage
dynamic()andgetServerSidePropswhere applicable. - Test Both Environments: Ensure your code runs smoothly on both server and client.
- Rely on Custom Hooks: Centralize browser-only logic in reusable hooks.
Frequently Asked Questions (FAQs)
Q1: Can I use localStorage or document in Next.js?
Yes, but ensure they're used only on the client side by checking typeof window !== 'undefined' or using useEffect.
Q2: Why does dynamic import fix the issue?
Dynamic import with ssr: false ensures the module is loaded only on the client, bypassing server-side execution.
Q3: What is the alternative to using window in SSR?
Look for libraries that are SSR-friendly or rewrite your logic to avoid browser-dependent code during SSR.
Q4: Does this affect SEO?
Using dynamic import or delaying rendering until client-side execution may affect SEO. Minimize such usage or ensure fallback content.
Conclusion
Resolving the "window is not defined" error in Next.js involves understanding the difference between server-side and client-side rendering. By following the solutions above, you can effectively handle this error and build robust, SSR-compatible applications.
