设计获取文档高度和宽度函数时遇到的问题
解决useWindowSize初始值无法获取body.offsetHeight的问题
问题原因
组件初始化时,useState的初始值是在组件挂载前计算的,这时候DOM树可能还没完全渲染完毕,document.body的内容还没加载或渲染完成,导致offsetHeight返回空值(比如0),看起来函数“无法正常工作”。
window.innerHeight是浏览器视口高度,不受DOM渲染状态影响,所以初始时能拿到有效值。- 窗口resize触发时,DOM已经完全渲染完成,
body.offsetHeight已经正确计算出文档整体高度,因此能正常返回。
修正后的代码
把初始尺寸的计算移到useEffect中,确保DOM渲染完成后再获取真实的文档高度,同时复用尺寸计算逻辑:
function useWindowSize() { const [size, setSize] = useState([0, 0]); // 先设占位初始值 useEffect(() => { // 抽离尺寸计算逻辑,复用初始和resize场景 const calculateSize = () => { setSize([document.body.offsetHeight, document.body.offsetWidth]); }; // 组件挂载时立即计算一次初始尺寸 calculateSize(); let timeoutId = null; const resizeListener = () => { clearTimeout(timeoutId); timeoutId = setTimeout(calculateSize, 150); }; window.addEventListener("resize", resizeListener); return () => { window.removeEventListener("resize", resizeListener); clearTimeout(timeoutId); // 清理定时器,避免内存泄漏 }; }, []); // 空依赖数组,确保只执行一次挂载逻辑 return size; }
额外说明
如果需要在DOM更新后立即同步获取尺寸(比如避免布局抖动),可以把useEffect换成useLayoutEffect,它会在DOM变更完成后同步执行,比useEffect的异步执行时机更早。
内容的提问来源于stack exchange,提问作者Botonian
相关产品推荐
相关产品推荐

