Infinite Query (무한스크롤)

모찌모찌·2024년 5월 11일

리액트쿼리

목록 보기
6/7

1. useInfiniteQuery 사용

useQuery()에서는 data에 한 페이지에 해당하는 데이터만 담고 있었지만, useInfiniteQuery()에서는 data모든 페이지의 데이터가 pages라는 프로퍼티로 배열에 담겨 있습니다.

import { useInfiniteQuery } from '@tanstack/react-query';

const {
  data: postsData,
  isPending,
  isError,
   hasNextPage,
  fetchNextPage,
  isFetchingNextPage,
} = useInfiniteQuery({
  queryKey: ['posts'],
  queryFn: ({ pageParam }) => getPosts(pageParam, PAGE_LIMIT),
  initialPageParam: 0,
  getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
    lastPage.hasMore ? lastPageParam + 1 : undefined,
});

useInfiniteQuery() 훅에서는 page param 값을 활용하여 페이지를 더 불러옵니다.

getNextPageParam() 함수에서 다음 페이지가 있는 경우 다음 page param 값을 리턴하는데요, fetchNextPage() 함수에서는 이렇게 리턴된 page param 값을 쿼리 함수로 전달해 다음 페이지의 데이터를 받아옵니다.

❗ 만약 getNextPageParams() 함수에서 undefinednull 값을 리턴하면 다음 페이지가 없는 것으로 간주fetchNextPage() 함수를 실행해도 더 이상 데이터를 받아오지 않고, hasNextPage의 값도 false가 됩니다.

2. pageParam 사용하기

initialPageParam: 0, // 0 페이지가 초기값
getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
  lastPage.hasMore ? lastPageParam + 1 : undefined,

✅ 파라미터

  • initialPageParam : 초기페이지 설정값

  • getNextPageParam : 다음 페이지의 설정값

    • lastPage : 현재까지 중 가장 마지막 페이지의 데이터가 전달
      (만약 현재 2 페이지에 해당하는 데이터까지 받아 왔다면 2 페이지의 데이터가 lastPage로 전달)

    • allPages : 모든 페이지의 데이터

    • lastPageParam : 현재까지 중 가장 마지막 페이지의 설정값
      (현재 2 페이지까지 받아 왔다면 lastPageParam은 2)

    • allPageParams : 모든 페이지의 각각의 페이지 설정값

✅ 동작 과정

getNextPageParam()에서는 파라미터로 받은 값들의 정보를 이용해 그 다음 페이지 값pageParam을 리턴해야 합니다.

이 프로젝트의 경우 현재 0 페이지라면 그다음 값은 1이 되어야 할 텐데요. 따라서 0 페이지의 데이터에서 hasMore 값을 확인 후, true인 경우 lastPageParam의 값인 0에 1을 더한 값 1을 리턴하도록 했습니다. false인 경우 undefinednull을 리턴해 주면 되는데, 이는 다음 페이지가 없다는 것을 의미합니다.

이 pageParam 값은 쿼리 함수의 파라미터로 전달되므로, 이 값을 이용해 백엔드에 해당 페이지에 해당하는 데이터를 요청할 수 있습니다. 따라서 쿼리 함수를 아래처럼 수정할 수 있는 것이죠.

queryFn: ({ pageParam }) => getPosts(pageParam, PAGE_LIMIT)


🔼 pages 배열의 0번 인덱스에는 첫 번째 페이지(0 페이지)의 데이터가, pageParams 배열의 0번 인덱스에는 첫 번째 페이지값인 0이 들어있는 것을 확인할 수 있습니다.

3. 다음 페이지 불러오기(fetchNextPage() 함수)

fetchNextPage() 함수를 실행하면 getNextPageParam() 함수의 리턴 값이 undefined나 null이 아닌 경우, 해당 리턴 값을 쿼리 함수의 pageParam으로 전달해 그다음 페이지 데이터를 가져옵니다.

	<div>
      <button onClick={fetchNextPage}>더 불러오기</button>
    </div>

4. 버튼 비활성화 처리하기

더 이상 불러올 데이터가 없거나 다음 데이터를 불러오는 중일 때에는 "더 불러오기" 버튼을 비활성화하겠습니다.

useInfiniteQuery()의 리턴 값 중 hasNextPageisFetchingNextPage를 이용하면 다음과 같이 간단히 구현할 수 있습니다.

const {
 data: postsData,
 isPending,
 isError,
 hasNextPage,
 fetchNextPage,
 isFetchingNextPage,
} = useInfiniteQuery({
 queryKey: ['posts'],
 queryFn: ({ pageParam }) => getPosts(pageParam, PAGE_LIMIT),
 initialPageParam: 0,
 getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
   lastPage.hasMore ? lastPageParam + 1 : undefined,
});

// ...

return (
   ...
       <button
     onClick={fetchNextPage}
     disabled={!hasNextPage || isFetchingNextPage}
   >
     더 불러오기
   </button>
   ...
);
profile
꼬꼬마 개발자 지망생

0개의 댓글