Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] React Query - useInfiniteQuery

Updated
2 min readView as Markdown
[ 살펴보기 ] React Query - useInfiniteQuery
C

A developer living in Busan, Korea

List 형식의 데이터를 불러올 때 pagination을 이용해 원하는 페이지에 해당하는 data list를 보여주는 것이 일반적일 것이다. 하지만 inifinite scroll과 같은 기능 구현에는 특정 페이지에 해당하는 data list가 아닌 기존 데이터 list + 새로운 데이터 list를 합친 모든 데이터 리스트를 사용자에게 보여 주어야 한다.

useInfiniteQuery는 이러한 infinite scroll 기능을 구현할 때 사용할 수 있다.

useInfiniteQuery

useInfiniteQuery의 기본형태는 다음과 같다

const { data, error, isFetching, isFetchingNextPage, fetchNextPage } = useInfiniteQuery({
  queryKey: ["user", "list"],
  queryFn: async ({ pageParam }) => {
    return await getUserList(pageParam);
  },
  initialPageParam: 1,
  getNextPageParam: (fetchedData, allFetchedData, currentPageCursor) => {
    return currentPageCursor + 1;
  },
});

일반적으로 쓰는 useQuery와는 차이점이 다소 보일 것이다. initialPageParam에는 가장 처음 fetch할 때 사용할 page 혹은 cursor 값을 설정해준다 그리고 initialPageParam에 설정한 값이 가장 처음 fetch할 때 queryFn param의 pageParam 값으로 사용된다

그 이후 fetchNextPage 함수를 통해 다음 데이터 fetch 요청을 하면 getNextPageParam에서 return한 값이 queryFn의 pageParam으로 사용되게 된다

useInfiniteQuery의 data

우선 주목해야 할 점은 useInfiniteQuery가 반환하는 data 객체가 useQuery가 반환하는 data와는 다르다는 점이다. useQuery와는 달리 useInfiniteQuery의 data 객체는 pages와 pageParams이라는 두 개의 프로퍼티를 가지고 있다.

pages에는 이때까지 fetch 했던 data가 array 형태로 들어가있고 pageParams은 data fetch시 썼던 page나 cursor 값을 배열로 가지고 있다

// useInfiniteQuery가 return한 data 객체
{
    "pages": [
        [
            {
                "id": 0,
                "name": "user-0",
                "page": "1"
            },
            {
                "id": 1,
                "name": "user-1",
                "page": "1"
            },
        ],
        [
            {
                "id": 0,
                "name": "user-2",
                "page": "2"
            },
            {
                "id": 1,
                "name": "user-3",
                "page": "2"
            },
        ]
    ],
    "pageParams": [
        1,
        2
    ]
}

InfiniteQuery에서 QueryKey

useInfiniteQuery를 사용할 때 주의할 점은 데이터 요청시 들어가는 queryParam이나 pathParam 또한 queryKey로 설정하는 useQuery와는 달리 useInfiniteQuery에서는 추가 요청시 변경되는 page 또는 cursor 값은 queryKey로 들어가지 않는다.

즉, 아래 예제처럼 useInfiniteQuery의 queryKey에는 변수나 state처럼 변경될 수 있는 dynamic한 값을 넣지 않는다. 만약 새로운 fetch가 발생했을 때 마다 queryKey 역시 영향을 받아 함께 변경되면 useInfiniteQuery가 반환하는 data는 매번 새로운 queryKey를 가진 새로운 데이터를 가지고 있게 된다. useInfiniteQuery은 기존의 데이터를 유지하며 새로운 데이터가 추가되는 동작을 구현하기 위해 사용하므로 이는 우리가 useInfiniteQuery를 사용해 구현하고자 하는 동작이 아닐 것이다.

...
  queryKey: ["user", "list"],
...

주의해야 할 사항

useInfiniteQuery의 fetchNextPage를 통해 data를 추가적으로 fetch할 때 isFetchingNextPage의 상태를 점검해서 isFetchingNextPage상태가 false일 때 fetchNextPage를 통해 추가 data fetch를 할 수 있게 조치가 필요하다. 그렇지 않으면 의도치 않게 데이터가 덮어 씌워져 버릴 위험이 있다.

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts