为何useCallback稳定化的ref回调获取高度为0,内联版本正常?
问题:useCallback包裹的ref回调无法正确获取元素高度
我有一个ShowMoreText组件,接收children作为props并将其渲染在带有回调ref的div中。但使用经useCallback稳定化的measureRef作为ref时,useEffect中的console.log输出childrenHeight为0,Show按钮也不显示;但使用内联ref回调时一切正常,请问这是为什么?
组件代码如下:
const ShowMoreText = (props: ShowLessOrMoreProps) => { const { children } = props; const [showMore, setShowMore] = useState<boolean>(false); const [showButton, setShowButton] = useState<boolean>(false); const [childrenHeight, setChildrenHeight] = useState<number>(9.5); const measureRef = useCallback((node: HTMLDivElement) => { if (node) { setChildrenHeight(node.getBoundingClientRect().height); } }, []); useEffect(() => { console.log(childrenHeight)// 当使用measureRef时输出0,内联版本则能得到正确高度,我不清楚原因 if (childrenHeight > 45) { setShowButton(true); } }, [childrenHeight]); return ( <Stack sx={{ alignItems: "flex-start", }} > <Collapse in={showMore} collapsedSize={45}> <div // ref={(node: HTMLDivElement) => { // setChildrenHeight(node?.getBoundingClientRect().height); // }} ref={() => measureRef} // 注释此代码并使用上方内联版本时一切正常 > {children} </div> </Collapse> {showButton && ( //使用measureRef时此按钮不会显示 <Button onClick={() => setShowMore((prev) => !prev)}> {showMore ? "Show less" : "Show more"} </Button> )} </Stack> ); };
原因及修复
核心问题
你传递ref的方式错误:
- 写
ref={() => measureRef}时,相当于给ref传了一个空壳函数——这个函数只会返回measureRef本身,但不会把React传入的DOM节点参数传递给measureRef。结果就是measureRef从未被真正调用,自然拿不到DOM节点的高度,childrenHeight始终停留在初始值(或后续错误的0),导致按钮无法显示。 - 内联版本的ref回调是直接接收React传入的DOM节点,调用
setChildrenHeight时能正确拿到高度,所以功能正常。
修复方法
直接将measureRef赋值给ref属性,不需要额外包裹函数:
<div ref={measureRef}> {children} </div>
补充说明:初始childrenHeight设为9.5,当无法获取正确高度时,这个值小于45,useEffect里的条件不满足,showButton不会被设为true,所以按钮不显示。
内容的提问来源于stack exchange,提问作者amir_70
相关产品推荐
相关产品推荐

