blindspot / frontend /src /rail /useInView.ts
yashwrites's picture
Signs on the film, draw tool, My search off by default, example films and Radiopaedia links (part 2)
2e6a666 verified
Raw History Blame Contribute Delete
865 Bytes
// True once the element has been on screen (round 5: debrief rows fetch their example films only when scrolled to).
// Without IntersectionObserver (old browsers, server rendering) it is true at once.
import { useEffect, useState, type RefObject } from 'react';
export function useInView(ref: RefObject<Element | null>, margin = '120px'): boolean {
const [seen, setSeen] = useState(() => typeof IntersectionObserver === 'undefined');
useEffect(() => {
if (seen) return;
const el = ref.current;
if (!el || typeof IntersectionObserver === 'undefined') { setSeen(true); return; }
const io = new IntersectionObserver((entries) => {
if (entries.some((e) => e.isIntersecting)) { setSeen(true); io.disconnect(); }
}, { rootMargin: margin });
io.observe(el);
return () => io.disconnect();
}, [ref, seen, margin]);
return seen;
}