React中如何将Navbar组件的dimensions更新值传递给Home组件?
解决父组件获取子组件DOM尺寸更新值的问题
方案1:移除Navbar内的dimensions状态,直接传递计算值
你原代码的核心问题是:setDimensions是异步操作,执行setHeight(dimensions.height)时拿到的还是旧状态值;同时空依赖的useEffect只执行一次,无法响应后续尺寸变化。如果Navbar自身不需要维护dimensions状态,完全可以直接计算尺寸后传给父组件:
修改后的Navbar.js:
const Navbar = ({ setHeight }) => { const refContainer = useRef(); const updateDimensions = () => { if (refContainer.current) { const { offsetWidth, offsetHeight } = refContainer.current; // 直接把计算出的高度传给父组件 setHeight(offsetHeight); // 若Navbar自身需要用尺寸,可存到ref里直接使用 // refContainer.dimensions = { width: offsetWidth, height: offsetHeight }; } }; useEffect(() => { // 初始化时获取一次尺寸 updateDimensions(); // 监听窗口resize,处理尺寸变化 window.addEventListener('resize', updateDimensions); return () => window.removeEventListener('resize', updateDimensions); }, [setHeight]); return ( <Container ref={refContainer}> </Container> ); };
Home.js保持不变即可,这样父组件能拿到Navbar的实时高度,包括窗口 resize 时的更新,不会出现无限循环。
方案2:保留Navbar内的dimensions状态,正确传递更新值
如果Navbar必须维护dimensions状态,需要避免状态更新引发的无限循环,同时确保传递最新值:
修改后的Navbar.js:
const Navbar = ({ setHeight }) => { const refContainer = useRef(); const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); // 用useCallback缓存函数,避免不必要的重渲染 const updateDimensions = useCallback(() => { if (refContainer.current) { const newDimensions = { width: refContainer.current.offsetWidth, height: refContainer.current.offsetHeight }; setDimensions(newDimensions); // 直接用计算好的newDimensions传递,不依赖异步更新后的state setHeight(newDimensions.height); } }, [setHeight]); useEffect(() => { updateDimensions(); window.addEventListener('resize', updateDimensions); return () => window.removeEventListener('resize', updateDimensions); }, [updateDimensions]); return ( <Container ref={refContainer}> </Container> ); };
关键修改说明:
- 用
useCallback包裹更新函数,确保只有依赖变化时才重新创建函数,避免useEffect重复执行。 - 计算出
newDimensions后直接传给父组件,跳过异步状态更新的等待,确保传递的是最新值。 - 添加窗口resize监听,保证尺寸变化时父组件能同步收到更新。
- 将缓存后的更新函数作为
useEffect依赖,确保回调更新时能重新绑定事件。
内容的提问来源于stack exchange,提问作者Devansh
相关产品推荐
相关产品推荐

