Expected Behaviour: IntersectionObserver
must correctly report the observed component’s visibility in the viewport.
Current Behaviour: IntersectionObserver
incorrectly reports component as invisible despite being in the viewport when another component is dragged and dropped to change the DOM layout.
My useOnScreen
hook –
// intersection observer is buggy with golden layout
// move C component and keep all in view, but B component will be marked not on screen
function useOnScreen(label, ref) {
const [isOnScreen, setIsOnScreen] = useState(false);
const observerRef = useRef(null);
useEffect(() => {
observerRef.current = new IntersectionObserver(
([entry]) => {
setIsOnScreen(entry.isIntersecting);
},
{ root: document.body }
);
}, []);
useEffect(() => {
observerRef.current.observe(ref.current);
return () => {
observerRef.current.disconnect();
};
}, [ref]);
return isOnScreen;
}
How I use this hook in my React component –
const Text = ({ label }) => {
const ref = useRef(null);
const onScreen = useOnScreen(label, ref);
useEffect(() => {
if (onScreen) {
console.log("onscreen", label);
return () => {
console.log("not on screen", label);
};
}
}, [onScreen, label]);
return <h1 ref={ref}>{label}</h1>;
};
Demo Video of the bug: https://drive.google.com/file/d/1W54-D3BT7FNqZNS4EzBDYdJFqdHD-iCx/view?usp=sharing
Code Setup for the bug: https://codesandbox.io/s/golden-layout-react-intersection-observer-zhnq3c?file=/src/App.js:289-615
My Approach
- I noticed that
rootBounds.width
androotBounds.height
are0
in theIntersectionObserverEntry
for componentB
when DOM layout is changed on drag/drop of componentC
. - Hence, it feels component
B
is not in view because the viewport is of0
size - I even tried with passing
options.root = document.body
while creating theIntersectionObserver
in its constructor but still same issue. - If I chose to ignore the callback when
rootBounds
is of0
size, I will then miss legit cases where a componentB
is not in viewport but the hook will still keep it as visible. - The next solution I think is to hook into
GoldenLayout
events to track which tabs are active and which are not and pass that prop to my Components somehow. - Is there a better solution here?