67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import React from "react";
|
|
|
|
type Param = {
|
|
elementRef?: React.MutableRefObject<Element | undefined>;
|
|
className?: string;
|
|
options?: IntersectionObserverInit;
|
|
removeIntersected?: boolean;
|
|
};
|
|
|
|
export default function useIntersectionObserver({
|
|
elementRef,
|
|
className,
|
|
options,
|
|
removeIntersected,
|
|
}: Param) {
|
|
const [isIntersecting, setIsIntersecting] = React.useState(false);
|
|
const [refresh, setRefresh] = React.useState(0);
|
|
|
|
const observerCallback: IntersectionObserverCallback = React.useCallback(
|
|
(entries, observer) => {
|
|
const entry = entries[0];
|
|
|
|
if (entry.isIntersecting) {
|
|
setIsIntersecting(true);
|
|
|
|
if (removeIntersected) {
|
|
observer.unobserve(entry.target);
|
|
}
|
|
} else {
|
|
setIsIntersecting(false);
|
|
}
|
|
},
|
|
[]
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
const element = elementRef?.current;
|
|
const elements = className
|
|
? document.querySelectorAll(`.${className}`)
|
|
: null;
|
|
|
|
if (!element && !className && refresh < 5) {
|
|
requestAnimationFrame(() => {
|
|
setTimeout(() => {
|
|
setRefresh(refresh + 1);
|
|
}, 2000);
|
|
});
|
|
return;
|
|
}
|
|
|
|
const observer = new IntersectionObserver(observerCallback, {
|
|
rootMargin: "0px 0px 0px 0px",
|
|
...options,
|
|
});
|
|
|
|
if (elements) {
|
|
elements.forEach((el) => {
|
|
observer.observe(el);
|
|
});
|
|
} else if (element) {
|
|
observer.observe(element);
|
|
}
|
|
}, [refresh]);
|
|
|
|
return { isIntersecting };
|
|
}
|