Next.js获取窗口尺寸时报无效Hook调用或window未定义如何解决?
报错原因&修复方案
- 如果你用的是Next.js 13+的App Router,所有组件默认是服务端组件,服务端运行环境不存在window对象,且服务端组件不允许使用React Hook(useState、useEffect都属于客户端Hook),直接写就会触发Hook调用错误或者window未定义错误。
- 原有代码在useState初始值中读取window,服务端渲染阶段会读到undefined,虽然做了判断但容易引发客户端和服务端渲染内容不一致的水合错误,且useEffect中没有做window存在性的兜底判断,极端场景下也会报错。
修复后完整代码
// 组件最顶部加这行,App Router必须加,Pages Router不需要 'use client' import { useState, useEffect } from 'react' // 防抖函数,避免resize频繁触发更新 function debounce(func, delay = 200) { let timeoutId return (...args) => { clearTimeout(timeoutId) timeoutId = setTimeout(() => func.apply(this, args), delay) } } export default function YourComponent() { const [width, setWidth] = useState(0) const [height, setHeight] = useState(0) const updateDimensions = debounce(() => { setWidth(window.innerWidth) setHeight(window.innerHeight) }) useEffect(() => { // 仅客户端执行,兜底判断window存在 if (typeof window === 'undefined') return // 首次挂载赋值初始尺寸 updateDimensions() // 绑定监听 window.addEventListener('resize', updateDimensions) // 卸载时移除监听 return () => window.removeEventListener('resize', updateDimensions) }, []) // 你的组件逻辑,比如给图片传宽高: // return <Image src="/xxx.jpg" width={width * 0.8} height={height * 0.5} alt="xxx" /> }
更优的图片适配方案
如果只是要实现图片的响应式适配,不需要自己监听窗口尺寸,用Next.js自带的next/image组件即可,直接配置sizes属性就能自动适配不同屏幕:
import Image from 'next/image' // 示例:移动端占满屏幕宽度,桌面端占80%宽度 <Image src="/example.jpg" fill sizes="(max-width: 768px) 100vw, 80vw" alt="示例图片" />
内容的提问来源于stack exchange,提问作者Skyler Gunn
相关产品推荐
相关产品推荐

