Gatsby: WebpackError: ReferenceError: window is not defined - Using Stateful functional component with hooks

Created on 9 Mar 2019  路  12Comments  路  Source: gatsbyjs/gatsby

I am trying to use a hook to determine the size of my window and am getting a build error when deploying to netlify

const toggle = () => setToggle(!isToggledOn); var windowSize = 900; if (window) { windowSize = useWindowSize(); } return ( WebpackError: ReferenceError: window is not defined

Here is my code

`import React, { useState, useEffect } from 'react';
import HeadLogo from './HeadLogo';
import useWindowSize from '@rehooks/window-size';
import TransitionLink from 'gatsby-plugin-transition-link';
import NavbarBrand from './styles/NavbarBrand';
import NavLinks from './styles/NavLinks';
import HamburgerMenu from './HamburgerMenu';
import isEntryExit from './isEntryExit';
import InnerDrop from './InnerDrop';

export default function Navbar() {
const [isToggledOn, setToggle] = useState(false);
const toggle = () => setToggle(!isToggledOn);
var windowSize = 900;
windowSize = useWindowSize();

return (


);
}
`

I have seen in other issues that set the function in a componentDidMount would solve the issue but that is not possible with hooks. Does anyone have any suggestions?

Thanks so much.

P.S this is my first post to GitHub :) So if I've left anything out of this question please let me know.

stale? question or discussion

Most helpful comment

Did you already try typeof window !== 'undefined'?

All 12 comments

Did you already try typeof window !== 'undefined'?

Try this

let windowsize = 900
if (typeof window !== 'undefined') {
 windowsize =  useWindowSize();
}

you probably want to define something closer to the actual object you want to use like:

let windowsize = { innerWidth: '900' }

can you please share your useWindowSize code also?

based on what you are trying to do, I think it should be something like this

function useWindowSize (defaultValue) {
  const [windowSize, setWindowSize] = useState({ innerWidth: defaultValue })

  useLayoutEffect(() => {
    setWindowSize({ innerWidth: window.innerWidth })
  }, [])

  return windowSize
}

then in your component

const windowSize = useWindowSize(900)

Hey @PatrickLambert1101

The ReferenceError error is occurring because window is not available during server side rendering (when gatsby build is run)

To fix this, you need to run this code only on the client side. You can do this by calling the hook inside an effect. Depending on your use case, you can use useEffect or useLayoutEffect

Guys, just a note:

You can do this by calling the hook inside an effect

In a (function-based) component, hooks should be called only at the top level. Doc ref

@PatrickLambert1101 you'd need to adjust the hook itself. Defining default values in the outside scope and using them as default state should do the trick:

let defaultHeight
let defaultWidth

if (typeof window !== `undefined`) {
  defaultHeight = window.innerHeight
  defaultWidth = window.innerWidth
}

const useWindowSize = () => {
  const [dimensions, setDimensions] = useState({
    windowHeight: defaultHeight,
    windowWidth: defaultWidth,
  })

  useEffect(() => {
    const handler = () => setDimensions({
      windowHeight: window.innerHeight,
      windowWidth: window.innerWidth,
    })

    window.addEventListener(`resize`, handler)
    return () => window.removeEventListener(`resize`, handler)
  }, [])

  return dimensions
}

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 馃挭馃挏

Hey again!

It鈥檚 been 30 days since anything happened on this issue, so our friendly neighborhood robot (that鈥檚 me!) is going to close it.

Please keep in mind that I鈥檓 only a robot, so if I鈥檝e closed this issue in error, I鈥檓 HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

Thanks again for being part of the Gatsby community!

@PatrickLambert1101 you'd need to adjust the hook itself. Defining default values in the outside scope and using them as default state should do the trick:

let defaultHeight
let defaultWidth

if (typeof window !== `undefined`) {
  defaultHeight = window.innerHeight
  defaultWidth = window.innerWidth
}

const useWindowSize = () => {
  const [dimensions, setDimensions] = useState({
    windowHeight: defaultHeight,
    windowWidth: defaultWidth,
  })

  useEffect(() => {
    const handler = () => setDimensions({
      windowHeight: window.innerHeight,
      windowWidth: window.innerWidth,
    })

    window.addEventListener(`resize`, handler)
    return () => window.removeEventListener(`resize`, handler)
  }, [])

  return dimensions
}

This solved my problem.

@Siregar
Where should I put this code ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

3CordGuy picture 3CordGuy  路  3Comments

benstr picture benstr  路  3Comments

magicly picture magicly  路  3Comments

ferMartz picture ferMartz  路  3Comments

timbrandin picture timbrandin  路  3Comments