React嵌套可展开容器组件状态不一致问题求助
问题分析与解决方案
问题根源
- 依赖数组触发时机错误:父容器的
useEffect仅监听expanded和children,但子容器展开/关闭时,父组件的children引用并未改变(子组件实例未更换,仅内部状态变化),导致父容器不会重新计算高度。 - 高度计算时机偏差:子容器状态变化时,父容器无法实时感知内容高度变化;偶尔触发计算时,DOM可能未完成更新,导致获取到错误的高度值。
修复方案:使用ResizeObserver监听内容高度变化
通过ResizeObserver可以实时监听容器内容的高度变化,不管是自身展开状态改变,还是子容器高度变化,都能自动更新父容器的maxHeight。
修改后的组件代码:
import { useRef, useState, useEffect } from 'react'; export default function ExpandableContainer({ expanded, children }) { const containerRef = useRef(null); const contentRef = useRef(null); const [style, setStyle] = useState({ maxHeight: 0 }); // 处理自身展开/收起的初始高度设置 useEffect(() => { if (expanded) { const height = contentRef.current.getBoundingClientRect().height; setStyle({ maxHeight: height }); } else { setStyle({ maxHeight: 0 }); } }, [expanded]); // 监听内容高度变化,实时更新maxHeight useEffect(() => { if (!expanded || !contentRef.current) return; const resizeObserver = new ResizeObserver((entries) => { entries.forEach(entry => { const height = entry.contentRect.height; setStyle({ maxHeight: height }); }); }); resizeObserver.observe(contentRef.current); return () => resizeObserver.disconnect(); }, [expanded]); return ( <div ref={containerRef} style={style} className='xxx'> <div ref={contentRef}> {children} </div> </div> ); }
方案说明
- 拆分两个
useEffect:一个处理自身expanded状态切换时的初始高度设置,另一个在展开状态下监听内容高度变化。 - 直接给内部内容容器绑定
ref,避免依赖DOM层级(原代码中ref.current.children[0]易受结构变更影响)。 ResizeObserver会自动捕捉子容器展开/关闭带来的高度变化,实时更新父容器的maxHeight,完全适配嵌套场景的需求。
内容的提问来源于stack exchange,提问作者TDUK
相关产品推荐
相关产品推荐

