使用React Hooks获取容器宽高是否有其他更简单的实现方法?
实现方案
你原有代码的核心问题在于:普通DOM元素本身不会触发resize事件(仅window对象支持该事件)、useEffect未加依赖数组导致反复绑定/解绑事件、获取的是窗口尺寸而非容器尺寸。我们可以用标准ResizeObserver API实现需求,这是目前监听元素尺寸变化的最优方案,完整可运行代码如下:
import { useState, useRef, useEffect } from 'react'; // 防抖工具函数 function debounce(fn, ms) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, ms); }; } export default function App() { const containerRef = useRef(null); const [dimensions, setDimensions] = useState({ height: 0, width: 0 }); useEffect(() => { const container = containerRef.current; if (!container) return; // 初始化时直接获取容器尺寸,解决首次渲染无正确值的问题 const updateDimensions = () => { const { width, height } = container.getBoundingClientRect(); setDimensions({ width, height }); }; updateDimensions(); // 用ResizeObserver监听容器本身的尺寸变化,替代无效的元素resize事件监听 const debouncedUpdate = debounce(updateDimensions, 300); const resizeObserver = new ResizeObserver(debouncedUpdate); resizeObserver.observe(container); // 清理逻辑,组件卸载时断开监听避免内存泄漏 return () => { resizeObserver.disconnect(); }; }, []); // 空依赖数组,仅在组件挂载时执行一次 // 此处可直接使用dimensions的宽高完成业务逻辑 console.log('当前容器尺寸:', dimensions); return ( <div className='container' ref={containerRef}> My Container </div> ); }
方案说明
- 解决了获取容器自身尺寸的需求:通过
getBoundingClientRect直接读取容器宽高,ResizeObserver专门监听容器本身的尺寸变化,和窗口尺寸完全解耦 - 解决了首次渲染崩溃的问题:组件挂载后会立即执行一次尺寸更新逻辑,第一时间拿到正确的容器尺寸,不需要依赖错误的窗口初始值
- 符合简洁的最新实现规范:用
useRef绑定DOM元素,不需要通过getElementById查询DOM,符合React最佳实践,ResizeObserver是原生标准API,无需引入第三方依赖
内容的提问来源于stack exchange,提问作者Bhushan
相关产品推荐
相关产品推荐

