I have a component which take a children as props and render it inside a div which has a callback 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)// when use measureRef function it gives me 0 when using inline version this gives me correct height and I don't know why
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} // if I comment this and use the above commmented version everything works fine
>
{children}
</div>
</Collapse>
{showButton && ( //when using measureRef function this button won't display
<Button onClick={() => setShowMore((prev) => !prev)}>
{showMore ? "Show less" : "Show more"}
</Button>
)}
</Stack>
);
};
the problem is that when I use stable measureRef function the console log inside useeffect prints 0 but in inline ref version everythings works fine. can anyone explain me why ?
2
Answers
I found the solution and share it here in case anyone is curious or have a same problem. The problem was that the children that I passed to this component was something like this:
and because of the delay of request the div height was actually 0 at the beginning. so the actual code for callback ref worked correct and the problem raised because of the api call delay. the solution for me and the mistake that i had been made was not to render the above code conditionally like this:
hopefully this can help someone else.
You return a function but ref shoulb be an Object (of certain type)
Hence You probably return void function.
if You want to pass
(node: HTMLDivElement) => { // setChildrenHeight(node?.getBoundingClientRect().height); // }
use unreserved prop then.props.ref is reserved for useRef() hook .
Finally :
If for some reason Yuu want to save such contruction, do thi that way:
Where setChildrenHeight() returns correct object type proper po ref.