Next.js使用window时报ReferenceError: window is not defined如何解决
错误原因
Next.js 默认会在服务端执行组件的初始化渲染逻辑,而服务端运行环境不存在window对象,你直接在useState的初始值参数中调用window.innerWidth,服务端执行阶段就会抛出ReferenceError: window is not defined错误。
另外你提供的原有代码还存在几个可优化/语法问题:
- 未导入
useEffect就直接调用 - 组件
return语句写在了函数体外部 - 模板字符串语法错误,反引号应该包裹整个表达式
- 直接赋值
window.onresize会覆盖其他位置绑定的resize事件,且没有做事件清理,容易引发内存泄漏
修复方案
我们只需要把window相关的操作都放到仅在客户端执行的useEffect钩子中即可,修复后的完整代码如下:
import { useState, useEffect } from 'react' export const Dashboard = ({ children }) => { // 初始值先设为0,避开服务端调用window const [size, setSize] = useState(0) const updateSize = () => setSize(window.innerWidth) useEffect(() => { // 组件挂载时先初始化一次尺寸 updateSize() // 用addEventListener绑定事件,避免覆盖其他resize监听 window.addEventListener('resize', updateSize) // 返回清理函数,组件卸载时移除事件监听 return () => window.removeEventListener('resize', updateSize) }, []) // 空依赖数组保证只在挂载和卸载时执行一次 return ( <div className={`${toggleMenu || size >= 768 ? 'flex' : 'hidden'}`}>content</div> ) }
额外优化(可选)
如果首次渲染时出现hydration不匹配的警告,可以加一个挂载状态判断,等客户端完成挂载后再渲染依赖窗口尺寸的内容:
const [isMounted, setIsMounted] = useState(false) useEffect(() => { setIsMounted(true) }, []) if (!isMounted) return null // 或者返回骨架屏等占位内容
内容的提问来源于stack exchange,提问作者Tyler Morales
相关产品推荐
相关产品推荐

