It's not possible to know if arbitrary children are fully rendered without each one offering specialized callbacks. As such, it might be better to watch elements for size changes.
We can use ResizeObserver to our advantage here.
If we create a nested pair of div:
<div class="fixed_size_overflow_auto">
<div>
{children}
</div>
</div>
making the outer div have fixed dimensions, we can listen for resize on the inner div. When we detect those resizes, we can calculate if the outer div has overflowed by comparing its offsetHeight to its scrollHeight.
Here is the idea, wrapped up in a component that can be styled using styled-components:
const DetectContentResizeElement: FC<{
className?: string;
onContentResized?: (v: { hasOverflow: boolean }) => void;
}> = ({ children, onContentResized, className }) => {
const contentRef = useRef<HTMLDivElement>(null);
const outerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!contentRef.current || !outerRef.current) {
return;
}
const obs = new ResizeObserver(() => {
const hasOverflow =
(outerRef.current?.offsetHeight ?? 0) <
(contentRef.current?.offsetHeight ?? 0);
onContentResized?.({ hasOverflow });
});
obs.observe(contentRef.current);
return () => obs.disconnect();
}, [onContentResized]);
return (
<div className={className} ref={outerRef}>
<div ref={contentRef}>{children}</div>
</div>
);
};
You can fix the size of this component by "subclassing" it with styled-components:
const FixedHeight = styled(DetectContentResizeElement)`
height: 200px;
width: 200px;
border: solid 1px black;
overflow: auto;
`;
so now you can use this container and get events that tell you when it overflowed:
<FixedHeight
onContentResized={({ hasOverflow }) =>
console.log(`resized. hasOverflow: ${hasOverflow}`)
}
>
<SomeChildElement />
</FixedHeight>
See it in action in this codesandbox project (uses resize-observer-polyfill ponyfill for best compatibility)
useEffectscrollHeightvsoffsetHeightwhen you handle theonContentResizedevent. Let me know how you get on, and I'll make you a real answer if it helped.hasOverflowparam in theonContentResized. Maybe that will help. codesandbox.io/s/react-content-resized-detection-3f3gr