Window is not defined in Next.js React app

JavascriptReactjsnext.js

Javascript Problem Overview


In my Next.js app I can't seem to access window:

> Unhandled Rejection (ReferenceError): window is not defined

componentWillMount() {
    console.log('window.innerHeight', window.innerHeight);
}

Enter image description here

Javascript Solutions


Solution 1 - Javascript

̶A̶n̶o̶t̶h̶e̶r̶ ̶s̶o̶l̶u̶t̶i̶o̶n̶ ̶i̶s̶ ̶b̶y̶ ̶u̶s̶i̶n̶g̶ ̶p̶r̶o̶c̶e̶s̶s̶.̶b̶r̶o̶w̶s̶e̶r ̶ ̶t̶o̶ ̶j̶u̶s̶t̶ ̶e̶x̶e̶c̶u̶t̶e̶ ̶ ̶y̶o̶u̶r̶ ̶c̶o̶m̶m̶a̶n̶d̶ ̶d̶u̶r̶i̶n̶g̶ ̶r̶e̶n̶d̶e̶r̶i̶n̶g̶ ̶o̶n̶ ̶t̶h̶e̶ ̶c̶l̶i̶e̶n̶t̶ ̶s̶i̶d̶e̶ ̶o̶n̶l̶y̶.

But process object has been deprecated in Webpack5 and also NextJS, because it is a NodeJS variable for backend side only.

So we have to use back window object from the browser.

if (typeof window !== "undefined") {
  // Client-side-only code
}

Other solution is by using react hook to replace componentDidMount:

useEffect(() => {
    // Client-side-only code
})

Solution 2 - Javascript

Move the code from componentWillMount() to componentDidMount():

componentDidMount() {
  console.log('window.innerHeight', window.innerHeight);
}

In Next.js, componentDidMount() is executed only on the client where window and other browser specific APIs will be available. From the Next.js wiki:

> Next.js is universal, which means it executes code first server-side, > then client-side. The window object is only present client-side, so if > you absolutely need to have access to it in some React component, you > should put that code in componentDidMount. This lifecycle method will > only be executed on the client. You may also want to check if there > isn't some alternative universal library which may suit your needs.

Along the same lines, componentWillMount() will be deprecated in v17 of React, so it effectively will be potentially unsafe to use in the very near future.

Solution 3 - Javascript

If you use React Hooks you can move the code into the Effect Hook:

import * as React from "react";

export const MyComp = () => {

  React.useEffect(() => {
    // window is accessible here.
    console.log("window.innerHeight", window.innerHeight);
  }, []);

  return (<div></div>)
}

The code inside useEffect is only executed on the client (in the browser), thus it has access to window.

Solution 4 - Javascript

With No SSR

https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home

Solution 5 - Javascript

componentWillMount() lifecycle hook works both on server as well as client side. In your case server would not know about window or document during page serving, the suggestion is to move the code to either

Solution 1:

componentDidMount()

Or, Solution 2

In case it is something that you only want to perform in then you could write something like:

componentWillMount() {
    if (typeof window !== 'undefined') {
        console.log('window.innerHeight', window.innerHeight);
    }
}

Solution 6 - Javascript

In the constructor of your class Component you can add

if (typeof window === 'undefined') {
    global.window = {}
}

Example:

import React, { Component } from 'react'

class MyClassName extends Component {

    constructor(props){
        super(props)
        ...
        if (typeof window === 'undefined') {
            global.window = {}
        }
}

This will avoid the error (in my case, the error would occur after I would click reload of the page).

Solution 7 - Javascript

The error occurs because window is not yet available, while component is still mounting. You can access window object after component is mounted.

You can create a very useful hook for getting dynamic window.innerHeight or window.innerWidth

const useDeviceSize = () => {

  const [width, setWidth] = useState(0)
  const [height, setHeight] = useState(0)

  const handleWindowResize = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  }

  useEffect(() => {
    // component is mounted and window is available
    handleWindowResize();
    window.addEventListener('resize', handleWindowResize);
    // unsubscribe from the event on component unmount
    return () => window.removeEventListener('resize', handleWindowResize);
  }, []);

  return [width, height]

}

export default useDeviceSize 

Use case:

const [width, height] = useDeviceSize();

Solution 8 - Javascript

I have to access the hash from the URL so I come up with this

const hash = global.window && window.location.hash;

Solution 9 - Javascript

Best solution ever

import dynamic from 'next/dynamic';

const Chart = dynamic(()=> import('react-apexcharts'), {
    ssr:false,
})

Solution 10 - Javascript

I was facing the same problem when i was developing a web application in next.js This fixed my problem, you have to refer to refer the window object in a life cycle method or a react Hook. For example lets say i want to create a store variable with redux and in this store i want to use a windows object i can do it as follows:

let store
useEffect(()=>{
    store = createStore(rootReducers,   window.__REDUX_DEVTOOLS_EXTENSION__ && 
    window.__REDUX_DEVTOOLS_EXTENSION__())
 }, [])
 ....

So basically, when you are working with window's object always use a hook to play around or componentDidMount() life cycle method

Solution 11 - Javascript

Here's an easy-to-use workaround that I did.

const runOnClient = (func: () => any) => {
  if (typeof window !== "undefined") {
    if (window.document.readyState == "loading") {
      window.addEventListener("load", func);
    } else {
      func();
    }
  }
};

Usage:

runOnClient(() => {
// access window as you like
})

// or async
runOnClient(async () => {
// remember to catch errors that might be raised in promises, and use the `await` keyword wherever needed
})

This is better than just typeof window !== "undefined", because if you just check that the window is not undefined, it won't work if your page was redirected to, it just works once while loading. But this workaround works even if the page was redirected to, not just once while loading.

Solution 12 - Javascript

A bit late but you could also consider using Dynamic Imports from next turn off SSR for that component.

You can warp the import for your component inside a dynamic function and then, use the returned value as the actual component.

import dynamic from 'next/dynamic'

const BoardDynamic = dynamic(() => import('../components/Board.tsx'), {
  ssr: false,
})

<>
   <BoardDynamic />
</>

Solution 13 - Javascript

For such cases, Next.js has Dynamic Import.

A module that includes a library that only works in the browser, it's suggested to use Dynamic Import. Refer

Solution 14 - Javascript

Date: 06/08/2021

Check if the window object exists or not and then follow the code along with it.

 function getSelectedAddress() {
    if (typeof window === 'undefined') return;

    // Some other logic
 }

Solution 15 - Javascript

For Next.js version 12.1.0, I find that we can use process.title to determine whether we are in browser or in node side. Hope it helps!

export default function Projects(props) {
    console.log({ 'process?.title': process?.title });

    return (
        <div></div>
    );
}

1. From the terminal, I receive { 'process?.title': 'node' }

process.title === 'node'

2. From Chrome devtool, I revice { 'process?.title': 'browser' }

process.title === 'browser'

Solution 16 - Javascript

You can define a state var and use the window event handle to handle changes like so.

const [height, setHeight] = useState();

useEffect(() => {
    if (!height) setHeight(window.innerHeight - 140);
    window.addEventListener("resize", () => {
        setHeight(window.innerHeight - 140);
    });
}, []);

Solution 17 - Javascript

If it is NextJS app and inside _document.js, use below:

<script dangerouslySetInnerHTML={{
        __html: `
            var innerHeight = window.innerHeight;
        `
        }} />

Solution 18 - Javascript

global?.window && window.innerHeight

It's important to use the operator ?., otherwise the build command might crash.

Solution 19 - Javascript

I want to leave this approach that I found interesting for future researchers. It's using a custom hook useEventListener that can be used in so many others needs.

Note that you will need to apply a little change in the originally posted one, like I suggest here.

So it will finish like this:

import { useRef, useEffect } from 'react'

export const useEventListener = (eventName, handler, element) => {
  const savedHandler = useRef()

  useEffect(() => {
    savedHandler.current = handler
  }, [handler])

  useEffect(() => {
    element = !element ? window : element
    const isSupported = element && element.addEventListener
    if (!isSupported) return

    const eventListener = (event) => savedHandler.current(event)

    element.addEventListener(eventName, eventListener)

    return () => {
      element.removeEventListener(eventName, eventListener)
    }
  }, [eventName, element])
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLeon GabanView Question on Stackoverflow
Solution 1 - JavascriptDarryl RNView Answer on Stackoverflow
Solution 2 - JavascriptAlexander StaroselskyView Answer on Stackoverflow
Solution 3 - JavascriptRotaretiView Answer on Stackoverflow
Solution 4 - JavascriptKateView Answer on Stackoverflow
Solution 5 - JavascriptRAVINDER MAHAJANView Answer on Stackoverflow
Solution 6 - JavascriptRealScatmanView Answer on Stackoverflow
Solution 7 - JavascriptIsmoil ShokirovView Answer on Stackoverflow
Solution 8 - JavascriptU.AView Answer on Stackoverflow
Solution 9 - JavascriptVinicius PolloView Answer on Stackoverflow
Solution 10 - JavascriptcrispengariView Answer on Stackoverflow
Solution 11 - Javascriptroj1512View Answer on Stackoverflow
Solution 12 - JavascriptParsa SafaviView Answer on Stackoverflow
Solution 13 - JavascriptSan-MakView Answer on Stackoverflow
Solution 14 - JavascriptMohamed JakkariyaView Answer on Stackoverflow
Solution 15 - JavascriptW.K.CView Answer on Stackoverflow
Solution 16 - JavascriptSeth SamuelView Answer on Stackoverflow
Solution 17 - JavascriptLakshit NagarView Answer on Stackoverflow
Solution 18 - JavascriptlucgauerView Answer on Stackoverflow
Solution 19 - JavascriptLianelView Answer on Stackoverflow