- data: Infinite Query 결과 데이터
브라우저 viewport와 원하는 요소의 교차점을 관찰하며, 요소가 viewport에 포함 되는지 구별하는 기능
Intrersection Observer사용을 위한 hook 만들어주기
import { RefObject, useEffect, useState } from "react";
function useIntersectionObserver(
elementRef: RefObject<Element>,
{ threshold = 0.1, root = null, rootMargin = "0%" }
) {
const [entry, setEntry] = useState<IntersectionObserverEntry>();
const updateEntry = ([entry]: IntersectionObserverEntry[]): void => {
setEntry(entry);
};
useEffect(() => {
const node = elementRef?.current;
const hasIOSupport = !!window.IntersectionObserver;
if (!node || !hasIOSupport) return;
const observerParams = { threshold, root, rootMargin };
const observer = new IntersectionObserver(updateEntry, observerParams);
observer.observe(node);
return () => observer.disconnect();
}, [elementRef?.current, root, rootMargin, JSON.stringify(threshold)]);
return entry;
}
export default useIntersectionObserver;
(useIntersectionObserver 부분만 코드 포스팅)
...
const ref = useRef<HTMLDivElement | null>(null);
const pageRef = useIntersectionObserver(ref, {});
const isPageEnd = !!pageRef?.isIntersecting;
const [pageEnd, setPageEng] = useState<boolean>(false);
const fetchProjects = async ({ pageParam = "1" }) => {
const { data } = await axios("/api/stores?page=" + pageParam, {
params: {
limit: 10,
page: pageParam,
},
});
return data;
};
const {
data: stores,
isFetching,
fetchNextPage,
isFetchingNextPage,
hasNextPage,
isError,
isLoading,
} = useInfiniteQuery("stores", fetchProjects, {
getNextPageParam: (lastPage: any) =>
lastPage.data?.length > 0 ? lastPage.page + 1 : undefined,
});
const fetchNext = useCallback(async () => {
const res = await fetchNextPage();
if (res.isError) {
console.log(res.error);
}
}, [fetchNextPage]);
useEffect(() => {
let timerId: NodeJS.Timeout | undefined;
if (isPageEnd && hasNextPage) {
timerId = setTimeout(() => {
fetchNext();
}, 500);
}
return () => clearTimeout(timerId);
}, [fetchNext, hasNextPage, isPageEnd]);
return (
...생략...
{(isFetching || hasNextPage || isFetchingNextPage) && <Loader />}
<div className="w-full touch-none h-10 mb-10 " ref={ref} />
)
...