【问题标题】:Window is not defined with custom react hook窗口未使用自定义反应挂钩定义
【发布时间】:2021-11-18 06:47:53
【问题描述】:

我面临一个似乎无法解决的问题。

我有一个自定义钩子来设置窗口的高度和宽度。但是由于 nextjs 是 SSR 我得到了窗口未定义的错误。

我的问题在于将钩子放在 if 语句或 useeffect 钩子中。

当前代码(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
}

当前代码:

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
    }

我不能将 getWindowDimensions() 放在 useEffect 中,因为钩子的规则

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

【问题讨论】:

标签: reactjs react-hooks next.js


【解决方案1】:

您收到错误是因为在 Next.js 中,您的代码首先在服务器端呈现,并且在服务器上没有像 windowdocument 等浏览器全局变量。要修复它,您可以这样做:

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
}

它会起作用,因为useEffect 保证只在客户端运行。

如果您希望创建一个为您处理此问题的钩子,请参阅:Window is not defined in Next.js React appHow to detect window size in Next.js SSR using react hook?

【讨论】:

    【解决方案2】:

    检查window是否已定义:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-05
      相关资源
      最近更新 更多