Next.js中在useEffect内设置window.innerWidth及自定义useWindowSize钩子初始值配置问题
在Next.js中修复useWindowSize钩子的初始值问题
我明白你遇到的问题了——在Next.js这类SSR框架里,自定义的useWindowSize钩子初始值为null,只有窗口 resize 后才更新,这是因为服务端渲染阶段根本没有window对象,导致初始状态没正确设置。下面我给你两种可靠的解决办法,帮你搞定初始值的问题:
方法一:在useState初始化时区分服务端/客户端
直接在useState的函数式初始化中判断环境,客户端直接获取当前窗口尺寸,服务端返回一个合理的默认值(比如0或者你预期的初始宽度):
import { useState, useEffect } from 'react'; export function useWindowSize() { // 函数式初始化只会执行一次,避免重复判断window const [windowSize, setWindowSize] = useState(() => { if (typeof window !== 'undefined') { // 客户端环境:直接获取当前窗口宽高 return { width: window.innerWidth, height: window.innerHeight, }; } // 服务端环境:返回默认值,可根据需求调整(比如移动端默认宽度375) return { width: 0, height: 0 }; }); useEffect(() => { const handleResize = () => { setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); }; // 监听窗口 resize 事件 window.addEventListener('resize', handleResize); // 清理事件监听 return () => window.removeEventListener('resize', handleResize); }, []); return windowSize; }
使用这个钩子时,初始值就会是客户端当前的窗口尺寸(服务端渲染时是默认值),不会再出现null的情况。
方法二:解决Hydration不匹配警告(可选)
如果服务端的默认值和客户端实际窗口尺寸差异较大,Next.js可能会抛出Hydration不匹配的警告。这时候可以在客户端挂载完成后,强制更新一次窗口尺寸:
import { useState, useEffect } from 'react'; export function useWindowSize() { const [windowSize, setWindowSize] = useState({ width: 0, height: 0 }); useEffect(() => { const handleResize = () => { setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); }; // 客户端挂载后立即更新一次,确保和实际窗口一致 handleResize(); // 监听 resize 事件 window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); // 服务端渲染时可以返回null或者默认值,客户端会很快更新 return typeof window !== 'undefined' ? windowSize : { width: 0, height: 0 }; }
这样既保证了服务端渲染时不会报错,客户端挂载后也能立刻拿到正确的初始值。
小提醒
你原来的代码里console.log(``, useWindowSize);是打印钩子函数本身,而不是它返回的状态值,应该改成console.log(windowSize);才能看到正确的窗口尺寸数据哦~
内容的提问来源于stack exchange,提问作者rbrtzlt
相关产品推荐
相关产品推荐

