모모 프로젝트에서 구현한 무한스크롤에 대해서 포스팅 해보겠습니다.
저는 지난번 솔로 프로젝트에서 라이브러리를 이용해서 무한스크롤을 구현해본 경험이 있는데요
이번에는 내장된 API인 observer API와 react-query의 useInfiniteQuery 훅으로 무한스크롤을 구현해 보았습니다.
무한 스크롤의 작동원리는 두 단계로 진행이 됩니다.
1. 스크롤이 뷰포트 바닥에 닿았는지 감지
2. 필요한 데이터 요청
useInfiniteQuery 사용하기
const {
data,
fetchNextPage,
hasNextPage,
isLoading,
isError,
}: UseInfiniteQueryResult<CardData[], unknown> = useInfiniteQuery(
['filteredList', keyword, selectedCategoryId, selectedLocationId],
({ pageParam = 1 }) => {
// 생략
return getList(urlPath, searchData, categoryId, locationId, pageParam);
},
{
getNextPageParam: (lastPage, allPages) => {
const nextPage = allPages.length + 1;
return lastPage.length === 0 ? undefined : nextPage;
},
},
);
useInfiniteQuery훅 실행으로 게시물 데이터 요청이 완료가 되면
getNextPageParam 콜백함수를 실행합니다.
이 함수는 두 가지 인자 (lastPage, allPages)를 전달받아서
return 된 값에 따라 요청 파라미터로 전달이 됩니다.
따라서, 게시물 데이터의 첫 페이지는 1이었으니 2, 3, 4 순으로 증가해야하며
마지막 페이지의 게시물 데이터를 만나게되면 undefined 를 return 해주어 마지막 페이지가 없음을 전달해주어야합니다.
lastPage, allPages의 형태는 아래와 같습니다.
console.log(lastPage, allPages)
데이터를 살펴보면 불러온 데이터의 마지막 페이지가 lastPage로
모든 페이지들이 각 요소로들어간 배열인 allPages로 들어가는걸 볼 수 있습니다.
따라서, allPages의 length보다 1큰 값이 nextPage가되고
lastPage의 length가 0이라면 데이터가 더이상 존재하지 않음으로 undefined를 return 하는 로직을 작성하였습니다.
스크롤감지 (observer API)
getNextPageParam 콜백함수로 useInfiniteQuery 리턴값인 hasNextPage가 다음 페이지가 있음을 알려주고
fetchNextPage로 다음 페이지를 fetch 합니다.
const scrollTargetRef = useRef(null);
useEffect(() => {
const handleScroll: IntersectionObserverCallback = (entries) => {
const target = entries[0];
if (target.isIntersecting && hasNextPage) {
fetchNextPage();
}
};
const observer = new IntersectionObserver(handleScroll, { threshold: 0.1 });
const target = scrollTargetRef.current;
if (target) {
observer.observe(target);
}
return () => {
if (target) {
observer.unobserve(target);
}
};
}, [hasNextPage]);
return (
<Wrapper>
// 생략
<div ref={scrollTargetRef}></div>
</Wrapper>
);
useRef로 가장 바닥에 있는 요소를 target으로 설정하여
target이 화면영역과 교차되는 순간 target.isIntersecting 이 true가 되면서
다음 페이지가 있으면(hasNextPage === true) fetchNextPage()를 실행합니다.
Ref
https://tanstack.com/query/v4/docs/react/reference/useInfiniteQuery
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
'Projects' 카테고리의 다른 글
[모모] 라이트하우스 성능 개선기 (0) | 2023.10.25 |
---|---|
[모모] 리액트에서 파일 업로드하기(사용자 프로필 사진 바꾸기) (0) | 2023.09.06 |
[ESLint, Prettier, Git Hook, Husky] 팀원들과 코드 스타일을 맞추기 위해 설정하면 좋은 툴 (0) | 2023.08.27 |
[모모] React-Query의 캐싱기능으로 api요청을 줄여보자 (6) | 2023.08.10 |