Next.js SSR环境下自定义React Hook报window is not defined问题求解
错误根因
你的错误出在服务端渲染阶段执行了调用window的逻辑:Next.js SSR 运行在 Node 环境,不存在window对象,你原代码中useState初始化时直接调用了getWindowDimensions(),服务端渲染执行到这一步就会抛出window未定义的错误。
修复后的自定义Hook代码
useWindowDimensions.tsx修改如下:
import { useState, useEffect } from 'react' function getWindowDimensions() { const { innerWidth: width, innerHeight: height } = window return { width, height, } } export default function useWindowDimensions() { // 初始化给服务端可正常运行的默认值,不要直接调用getWindowDimensions const [windowDimensions, setWindowDimensions] = useState({ width: 0, height: 0 }) useEffect(() => { // 仅在客户端挂载后执行,获取真实窗口尺寸 setWindowDimensions(getWindowDimensions()) function handleResize() { setWindowDimensions(getWindowDimensions()) } window.addEventListener('resize', handleResize) return () => window.removeEventListener('resize', handleResize) }, []) return windowDimensions }
业务代码适配说明
如果不想在客户端挂载前触发错误的尺寸计算,可以加一层客户端挂载判断,避免服务端渲染阶段计算出不符合预期的结果:
const { height, width } = useWindowDimensions() const [isClient, setIsClient] = useState(false) useEffect(() => { setIsClient(true) }, []) const dimensions = () => { // 服务端渲染阶段直接返回默认值 if (!isClient) return 0 if (width > 1900) return width * 0.4 if (width > 1000) return width * 0.3 if (width > 800) return width * 0.2 return width * 0.1 }
如果担心页面初始加载有尺寸闪烁,可以在isClient为false时渲染骨架屏/占位内容,等客户端挂载完成后再渲染真实内容即可。
内容的提问来源于stack exchange,提问作者elmgren
相关产品推荐
相关产品推荐

