Published on

Fixing 'Window is Not Defined' Error in Next.js

Authors
  • Name
    Ripal & Zalak
    Twitter

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

  1. Accessing window in React lifecycle methods like componentWillMount.
  2. Using libraries that directly access window.
  3. 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

  1. Always Check for Environment: Use typeof window !== 'undefined' before accessing browser-specific objects.
  2. Use Next.js Features: Leverage dynamic() and getServerSideProps where applicable.
  3. Test Both Environments: Ensure your code runs smoothly on both server and client.
  4. 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.