We use cookies for site analytics. Accept to help us understand how the site is used. See our Privacy Policy for details.
A medium frontend problem, graded against 5 test cases (2 of them hidden).
React and browser-platform problems - hooks, event handling, and rendering behaviour.
Reach for it when you see: A component, hook, or DOM-behaviour question rather than an algorithm.
More Frontendproblems →```tsx
export function useIntersectionObserver(
ref: React.RefObject<Element>,
options?: IntersectionObserverInit
) {
const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);
useEffect(() => {
if (!ref.current) return;
const observer = new IntersectionObserver(([e]) => setEntry(e), options);
observer.observe(ref.current);
return () => observer.disconnect();
}, [ref, JSON.stringify(options)]); // serialize options as dep proxy
return entry;
}
// Usage: lazy-load images
function LazyImage({ src, alt }: { src: string; alt: string }) {
const ref = useRef<HTMLImageElement>(null);
const entry = useIntersectionObserver(ref, { threshold: 0.1, rootMargin: "100px" });
const visible = entry?.isIntersecting ?? false;
return <img ref={ref} src={visible ? src : undefined} alt={alt} />;
}
```
Common uses:
- Infinite scroll (observe a sentinel at list end; when it's visible, load more).
- Lazy-load images / heavy components.
- Track viewport analytics ("user actually saw this content").
- Pause expensive offscreen work.
Threshold semantics: the callback fires when the visible ratio crosses any threshold. `threshold: [0, 0.25, 0.5, 0.75, 1]` fires 5 times during a smooth scroll. Use `threshold: 0` for "any pixel visible" toggling. Use `rootMargin: "100px"` to trigger 100px *before* visibility for prefetching.
The full reference solution in every supported language stays in the editor above - reveal it there once you have had a real attempt.
Read off this problem's own test suite, so these are the cases a submission actually has to survive.
These apply to the pattern as a whole, not just this problem.