React Query(리액트 쿼리) - Infinite Queries

iskkiri2024년 09월 22일
Infinite Scroll
무한 스크롤
React Query
Infinite Queries
useInfiniteQuery
React Query(리액트 쿼리) - Infinite Queries

이번 글에서는 React Query의 Infinite Queries에 대해서 알아보겠습니다.

 

코드와 예제 결과는 Codesandbox에서 직접 확인할 수 있습니다.

 

 

Infinite Queries

 

기존 데이터에 새 데이터를 불러오기 위한 “더 보기” 버튼나 “무한 스크롤” 방식은 매우 일반적인 UI 패턴입니다. React Query는 이러한 리스트를 쿼리하기 위한 useQuery의 확장 버전인 useInfiniteQuery를 제공합니다.

 

useInfiniteQuery

 

기본적인 useInfiniteQuery의 구조

 

useInfiniteQuery에는 useQuery와는 다른 옵션 몇 가지 사항이 있습니다:

 

  1. data.pages: 데이터를 여러 페이지에 걸쳐 페칭하며, 각 페이지는 data.pages 배열에 저장됩니다. 새로운 페이지가 로드되면 이 배열에 추가됩니다.
  2. fetchNextPage: 추가 데이터를 가져오기 위해 사용하는 함수입니다. 이 함수는 현재 페이지 이후의 데이터를 페칭합니다.
  3. initialPageParam: 첫 번째 페이지를 페칭할 때 사용할 파라미터입니다. 이 값은 쿼리를 시작할 때 반드시 필요합니다.
  4. getNextPageParam: 다음 페이지를 페칭할 때 사용할 정보를 반환하는 함수입니다. 이 함수는 현재 페이지 데이터를 기반으로 다음 페이지 번호나 조건을 결정합니다.
  5. hasNextPage: 다음 페이지가 있는지 여부를 나타내는 불리언 값입니다. getNextPageParam 함수가 undefined 또는 null을 반환하면 이 값은 false가 됩니다.
  6. 로딩 상태: isFetchingNextPage는 다음 페이지를 가져오는 중인지, isFetchingPreviousPage는 이전 페이지를 가져오는 중인지를 나타냅니다.

 

예제 코드 설명

 

예제 코드는 무한 스크롤을 구현하는 방식으로 작성되었습니다. 
intersection observer를 이용한 무한 스크롤 구현의 경우에는 Intersection Observer API를 이용하여 Infinite Scroll 구현하기를 참고해주세요.

 

export default function InfiniteQueriesPage() {

								.
								.
								.

  const { data, hasNextPage, fetchNextPage } = useInfiniteQuery({
    queryKey: ["POSTS", "INFINITE"],
    queryFn: ({ pageParam: page }) => getPostsApi({ page }),
    initialPageParam: 1,
    getNextPageParam: (lastPage) => {
      if (!lastPage.pagination.hasNextPage) {
        return undefined;
      }
      return lastPage.pagination.currentPage + 1;
    },
  });

  const posts = useMemo(() => {
    if (!data) return [];
    return data.pages.flatMap((page) => page.data);
  }, [data]);

  useEffect(() => {
    if (!inView || !hasNextPage) return;
    fetchNextPage();
  }, [fetchNextPage, hasNextPage, inView]);

  return (
  								.
  								.
  								.
  );
}

 

  1. useInfiniteQuery는 useQuery와 동일하게 queryKey와 queryFn을 설정합니다. 차이점은 useInfiniteQuery의 queryFn의 함수 인자로 pageParam을 제공해준다는 점입니다.
  2. initialPageParam: 첫 번째 페이지를 로드할 때 사용됩니다. 예제에서는 첫 번째 페이지로 1을 설정했습니다.
  3. getNextPageParam: 다음 페이지가 존재하는 경우 다음 페이지 번호를 반환하고, 없을 경우 undefined를 반환합니다. 이 값이 undefined 또는 null이면 hasNextPage는 false가 됩니다.
  4. fetchNextPage: 사용자가 스크롤을 통해 마지막 지점에 도달하면, 이 함수가 호출되어 다음 페이지 데이터를 가져옵니다.

 

 

참고로, 이 블로그의 홈 화면에도 무한 스크롤이 적용되어 있으며, 이를 구현하기 위해 useInfiniteQuery를 사용했습니다. React Query의 useInfiniteQuery를 통해 데이터를 추가로 로드하는 무한 스크롤 기능을 간편하게 구현할 수 있습니다.

React Query(리액트 쿼리) - Infinite Queries