mirror of
https://github.com/p-stream/p-stream.git
synced 2026-03-11 17:55:33 +00:00
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.
49 lines
1.2 KiB
TypeScript
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,
|
|
};
|
|
}
|