p-stream/src/hooks/useIntersectionObserver.ts
Pas ebdb931d59 Add lazy loading for media carousels using Intersection Observer
Introduces a reusable useIntersectionObserver hook and a LazyMediaCarousel component to defer rendering of carousels until they are near the viewport. Updates discoverContent and AllMovieLists to use LazyMediaCarousel, improving performance by only loading carousels as needed. Priority carousels (e.g., top of page) are loaded immediately.
2025-12-01 16:57:17 -07:00

49 lines
1.2 KiB
TypeScript

import { useEffect, useRef, useState } from "react";
interface UseIntersectionObserverOptions {
threshold?: number;
root?: Element | null;
rootMargin?: string;
}
export function useIntersectionObserver<T extends HTMLElement = HTMLDivElement>(
options: UseIntersectionObserverOptions = {},
) {
const { threshold = 0.1, root = null, rootMargin = "0px" } = options;
const [isIntersecting, setIsIntersecting] = useState(false);
const [hasIntersected, setHasIntersected] = useState(false);
const elementRef = useRef<T | null>(null);
useEffect(() => {
const element = elementRef.current;
if (!element) return;
const observer = new IntersectionObserver(
([entry]) => {
const isElementIntersecting = entry.isIntersecting;
setIsIntersecting(isElementIntersecting);
if (isElementIntersecting && !hasIntersected) {
setHasIntersected(true);
}
},
{
threshold,
root,
rootMargin,
},
);
observer.observe(element);
return () => {
observer.unobserve(element);
};
}, [threshold, root, rootMargin, hasIntersected]);
return {
ref: elementRef,
isIntersecting,
hasIntersected,
};
}