Next.js添加'use client'后仍报window未定义的问题咨询
你遇到的情况是:给自定义Hook文件加上"use client"后,执行const [windowWidth, setWindowWidth] = useState(window.innerWidth);时会出现window对象相关错误,但应用并未崩溃、功能正常,使用的Next.js版本为v13.4.13。
代码示例
"use client"; import { useEffect, useState } from "react"; const useWindowWidth = (delay = 100): number => { const [windowWidth, setWindowWidth] = useState(window.innerWidth); useEffect(() => { ... }, []); return windowWidth; }; export default useWindowWidth;
问题原因
虽然你添加了"use client"指令,但Next.js中标记为客户端组件的文件依然会在服务器端完成首次渲染(SSR),这个指令只是界定了服务器组件和客户端组件的边界,让该文件及导入的模块后续在客户端进行交互逻辑处理。
而useState的初始值是在渲染阶段计算的,服务器端环境不存在window对象,所以直接调用window.innerWidth会触发错误。之所以应用没崩溃,是因为客户端接管后会重新渲染,覆盖掉服务器端的错误状态。
官方文档说明
在Next.js中使用客户端组件
要使用客户端组件,你可以在文件顶部、import语句上方添加React的"use client"指令。
"use client"用于声明服务器组件与客户端组件模块之间的边界。这意味着在文件中定义"use client"后,所有导入到该文件的其他模块(包括子组件)都将被视为客户端包的一部分,并将由React在客户端渲染。
解决方案
可以通过两种方式避免服务器端报错:
方式一:设置初始默认值,在useEffect中更新真实宽度
useEffect只会在客户端执行,所以可以把初始值设为0或其他默认值,再在副作用里获取window宽度并更新状态:const [windowWidth, setWindowWidth] = useState(0); useEffect(() => { setWindowWidth(window.innerWidth); // 监听窗口变化的逻辑... }, []);方式二:条件判断客户端环境
在计算useState初始值时,先判断是否存在window对象:const [windowWidth, setWindowWidth] = useState( typeof window !== 'undefined' ? window.innerWidth : 0 );
内容的提问来源于stack exchange,提问作者user884321

