Home > Net >  Window is not defined with custom react hook
Window is not defined with custom react hook

Time:09-25

I am facing a problem I can't seem to solve.

I have a custom hook that sets the height and width of the window. But since nextjs is SSR I get the error that window is not defined.

My problem lies in putting the hook in a if statement or useeffect hook.

Current code (useWindowDimensions.tsx):

import { useState, useEffect } from 'react'

function getWindowDimensions() {
    const { innerWidth: width, innerHeight: height } = window
    return {
        width,
        height,
    }
}

export default function useWindowDimensions() {
    const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions())

    useEffect(() => {
        function handleResize() {
            setWindowDimensions(getWindowDimensions())
        }

        window.addEventListener('resize', handleResize)
        // code here
        return () => window.removeEventListener('resize', handleResize)
    }, [])

    return windowDimensions
}

Current code:

const { height, width } = useWindowDimensions()

const dimensions = () => {
        if (width > 1900) return width * 0.4
        if (width > 1000) return width * 0.3
        if (width > 800) return width * 0.2
        if (width < 800) return width * 0.1
    }

I can't put getWindowDimensions() in an useEffect because the rules of hooks

useEffect(() => {
    function getWindowDimensions() {
        const { innerWidth: width, innerHeight: height } = window
        return {
            width,
            height,
        }
    }
})

CodePudding user response:

Check if window is defined or not:

if (typeof window !== 'undefined') {
  // You now have access to `window`
}

https://nextjs.org/docs/migrating/from-create-react-app#safely-accessing-web-apis

CodePudding user response:

You are getting the error because in Next.js your code is first server side rendered, and on server there are no browser globals like window, document, etc. To fix it, you can do this:

export default function useWindowDimensions() {
    const [windowDimensions, setWindowDimensions] = useState({width: 0, height: 0}) // <-- don't invoke here

    useEffect(() => {
        function handleResize() {
            setWindowDimensions(getWindowDimensions())
        }

        handleResize() // <-- invoke this on component mount
        window.addEventListener('resize', handleResize)
        
        return () => { window.removeEventListener('resize', handleResize) }
    }, [])

    return windowDimensions
}

It will work because useEffect is guaranteed to run on client side only.

Also refer: Window is not defined in Next.js React app and How to detect window size in Next.js SSR using react hook? if you wish to create a hook that handles this for you.

  • Related