1

I am trying to use a useState hook with the window property in Nextjs. However, I am getting the error, ReferenceError: window is not defined.

The goal: update the size state whenever the screen size changes

Implementation:

import { useState } from 'react'

export const Dashboard = ({ children }) => {

  const [size, setSize] = useState(window.innerWidth) // <<< Error thrown here
  const updateSize = () => setSize(window.innerWidth)
  useEffect(() => (window.onresize = updateSize))
}

return {
  <div className=`{$toggleMenu || size >= 768 ? 'flex' : 'hidden'}`}>content</div>
}

I've tried placing the useState in a conditional and useEffect hook, but this does not fix the issue.

Tyler Morales
  • 1,440
  • 2
  • 19
  • 56
  • 1
    `window` is not defined on the server side. since you have NextJS i'm assuming you're doing ssr and this is where the error is thrown. to resolve it, just check whether the window object exists before trying to access innerWidth, and also a check before adding the listener in your useEffect. – Ian J Miller Nov 18 '21 at 21:35
  • if (typeof window !== "undefined") { // browser code } I got this to work once I placed the useState outside of the conditional and then updated the state inside. – Tyler Morales Nov 18 '21 at 21:45
  • https://stackoverflow.com/questions/63406435/how-to-detect-window-size-in-next-js-ssr-using-react-hook – Ian J Miller Nov 18 '21 at 21:48
  • the useState doesnt need a conditional, just define a new variable above it or something. `const windowWidth = window?.innerWidth ?? 0;` then do `useState(windowWidth)` – Ian J Miller Nov 18 '21 at 21:49

1 Answers1

2

I recently did something similar and solved it by checking if the window object exists, like Ian commented.

const breakpoints = (width) => {
    if(width < 640) {
      return 'xs';
    } else if(width >= 640 && width < 768 ) {
      return 'sm';
    } else if(width >= 768 && width < 1024) {
      return 'md';
    } else if(width >= 1024) {
      return 'lg';
    }
  };
  
  const [breakpoint, setBreakpoint] = useState(() => breakpoints(typeof window !== 'undefined' && (window.innerWidth)));

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const calcInnerWidth = function() {
        setBreakpoint(breakpoints(window.innerWidth))
      }
      window.addEventListener('resize', calcInnerWidth)
      return () => window.removeEventListener('resize', calcInnerWidth)
    }
  }, [])

Useful links:

AlbinR
  • 396
  • 3
  • 8
  • Checking of (typeof window !== 'undefined') inside useEffect is not needed because it will only run after each render on client side – Laiacy Feb 03 '22 at 11:45