窗口未使用自定义反应挂钩定义

elm*_*ren 7 reactjs next.js react-hooks

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

我有一个自定义挂钩,用于设置窗口的高度和宽度。但由于 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
}
Run Code Online (Sandbox Code Playgroud)

当前代码:

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
    }
Run Code Online (Sandbox Code Playgroud)

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

useEffect(() => {
    function getWindowDimensions() {
        const { innerWidth: width, innerHeight: height } = window
        return {
            width,
            height,
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

brc*_*-dd 7

您收到错误是因为在 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
}
Run Code Online (Sandbox Code Playgroud)

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

另请参阅:Next.js React app 中未定义窗口如何使用 React hook 检测 Next.js SSR 中的窗口大小?如果您想创建一个为您处理此问题的钩子。