DEV Community

How to solve "window is not defined" errors in React and Next.js

Vincent Voyer on June 10, 2020

Next.js is a React framework with pre-rendering abilities. This means that for every page, Next.js will try to generate the HTML of the page for be...
Collapse
 
rowin1125 profile image
Rowin Mol • Edited

Niceee!

If you don't want to have a lot of boilerplate code, you could simple write:

const isBrowser = window && window.addEventListener(.......blabla)
Enter fullscreen mode Exit fullscreen mode

and use this variable as a conditional.

Also if you use the first option, please remember to unsubscribe your eventListener in the useEffect or you gonna have a bad time 😭 .

useEffect(function onFirstMount() {
    function onScroll() {
      console.log("scroll!");
    }

    window.addEventListener("scroll", onScroll);

   return () => {
      window.removeEventListener("scroll");
    }
  }, []);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vvo profile image
Vincent Voyer • Edited

Hey there Rowin, you might have a different setup but const isBrowser = window won't work at least in Next.js pre-rendering. You'll get the same error (just tried it again). I think anytime such code would go through Node.js it would fail, as shown in a REPL:

> node
Welcome to Node.js v12.18.0.
Type ".help" for more information.
> window && "ok"
Uncaught ReferenceError: window is not defined
Enter fullscreen mode Exit fullscreen mode

As for unsubscribing the listener, this is already done in the code samples from the article so maybe you missed that or there's some other place I forgot to do it?

Thanks

Collapse
 
teamroggers profile image
Rogier Nitschelm

Perhaps like this?

const isBrowser = () => typeof window !== "undefined"

// node
isBrowser() // false

// browser
isBrowser() // true
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
vvo profile image
Vincent Voyer

Yes that would work indeed! Thanks :)

Thread Thread
 
vvo profile image
Vincent Voyer

Just added a new solution and thank you note :)

Thread Thread
 
ariyou2000 profile image
ARiyou Jahan

In a tread related to this problem in Next.JS official GitHub issue page mentioned that it is wrong to do so and you need to explicitly check typeof window !== "undefined" wherever you need it:
NextJS GitHub issues page

Consider reading my solution as well. it's inspirred by this post. So thank you Vincent for idea.
NextJS - Access window and localStorage

Collapse
 
clxrityy profile image
clxrity

I found this only works (2024) when adding window to the dependency array.

Collapse
 
jmsunseri profile image
Justin Sunseri

none of these solutions work well if the problem is in a library you are using

Collapse
 
vvo profile image
Vincent Voyer

Definitely right. When that's the case I am not sure if there's even a solution. Do you know one? If the library tries to read directly from the window object, then it just isn't compatible with Node.js (even if it could I guess).

Maybe you can do something like global.window = {} and provide the necessary code? Let us know!

Collapse
 
jmsunseri profile image
Justin Sunseri

My solution was to import the component that used the library that used window using the dynamic importer

import dynamic from 'next/dynamic';
...
const Standings = dynamic(() => import('../components/Standings/Standings'), {
  ssr: false,
});
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
vvo profile image
Vincent Voyer

Thanks, if I am not mistaken, that's the third solution of this current blog post: dev.to/vvo/how-to-solve-window-is-...

Thread Thread
 
jmsunseri profile image
Justin Sunseri

I feel silly now.

Thread Thread
 
alsmith808 profile image
Alan Smith

Lol!!

Thread Thread
 
vvo profile image
Vincent Voyer

Hey Justin, don't, because I am updating the article right now to add that this particular solution works well for libraries you're importing :) Thanks for the tip!

Collapse
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

As a good practice, I would suggest to convert this into a customHook like that:

import { useEffect } from 'react';

export default function useScroll(callback) {
  useEffect(function mount() {
    function onScroll() {
      const scrollPosition = window.scrollY;
      callback(scrollPosition);
    }

    window.addEventListener('scroll', onScroll);

    return function unMount() {
      window.removeEventListener('scroll', onScroll);
    };
  });

  return null;
}

so you can use it in multiple places like:

import useScroll from '../customHooks/useScroll';

export default function whatever() {

  useScroll( (val) => { 
     // add any logic with val
  });

  // component logic
  return (  {/*component structure*/} );

This is just an example, it can be extended adding an "element" parameter and some logic for it in the hook so you can get the scroll position of any element and get back the value to do something with it in the callback.

This avoid the need of creating different functions that performs almost the same actions and it's more in line with what hooks are (high order functions).

Collapse
 
acushlakoncept_31 profile image
Uduak Essien

Even better

Collapse
 
polobustillo profile image
PoloBustillo

Nice work
I was struggling a little with adding a function that is not a default export to run with SSR false, maybe this could be helpful for someone:

import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)

Collapse
 
musiuralamopu profile image
Musiur Alam Opu • Edited

Thanks a lot ...

if (typeof window !== "undefined") {
// browser code
}

this one works for me....

I wanted to redirect to other page using window.location.replace....but several times it threw the error that window is not defined....Basically in HOC there was a class component and inside the render block before the returnning the Original component I wanted to check if a variable is true or not....Hence I made a condition which will redirect to other page if variable is false....

Thanks again!

Collapse
 
okumujustine profile image
okumujustine

so helpful👏

Collapse
 
rahulsapkota profile image
Rahul Sapkota

Hello,
I am trying to convert html template into reactjs component in reactjs app. I am injecting the js required like this shown in below image.

Image description

the js file contains initialization and method invoke as shown in below image.

Image description

Image description

and i am getting error like this as shown below image, how do i fix it or rather a good way how it's done so i can use every plugin mentioned in this file without error. please help me on this.

Image description

Collapse
 
anwaransari profile image
MD Anwar • Edited

Thanks alot, 3rd solution worked for me, i am new in next js and used the reactjs-social-login npm dependency.
And were having a page map to the login in single page but whenever i tried to refresh page it was throwing "Window is not defined" so i just copied social login button and dependencies and created new functional component and dynamically imported in parent login page and it's working fine.

Collapse
 
acushlakoncept_31 profile image
Uduak Essien

Thank you so much, the second solution worked perfectly for me

Collapse
 
sohanemon profile image
Sohanur Rahman Emon

It really helpful.

Collapse
 
tahijameel profile image
TahiJameel

Thanks for this helpful article

Collapse
 
truongdinh2 profile image
truongdinh2

thank you, but I only want show model when scroll. It seems re-render so many.

Collapse
 
doctorderek profile image
Dr. Derek Austin 🥳

Love it, thanks! I didn't know about the Next.js dynamic importer, but that's great for cases like this. 💯

Collapse
 
beulahpt profile image
Beulah Sheeba

Hi How can I solve this in react js with out next?

Collapse
 
vvo profile image
Vincent Voyer

The blog post has Next.js in it but really all techniques (but the dynamic loading one) will work everywhere, so try them and let us know

Collapse
 
copperfox777 profile image
copperfox777

Good article!

Collapse
 
bl4ckck profile image
bl4ckck

how to load variable?

example:

var myVar = "bla"

When I use dynamic loading, it returns ReferenceError: window is not defined

Collapse
 
kritish58 profile image
Rishi58

Thanks 👍

Collapse
 
osamad profile image
Osama-D

i had to create an account to say Thank you So much the third solution saved my day ^^

Collapse
 
natashajaved profile image
natashajaved • Edited

What if I want to find geolocation using navigator object in getStaticProps and make api request on that basis and use the response to fill data in pre rendering. Need to do this for SEO

Collapse
 
theo_tran_880fc397a35366f profile image
Theo Tran

For anyone still dealing with this issue, I used the isBrowser check along with Reacts lazy module to lazyload the import and Suspense wrapped the component being rendered.