[React Query] useInfiniteQuery

HYl·2022년 4월 11일
3

React Query

목록 보기
4/4

useInfiniteQuery 를 사용하여 무한 스크롤을 구현해보자.


useQuery를 쓸 때는, data가 API로 받은 data에 직접적으로 접근한다.
반면에, useInfiniteQuery는 useQuery와 다른 구조인 pageParamspages 를 받게된다.

이전의 글에서 작성하였던 data를 가져오자.

위의 데이터를 useInfiniteQuery를 이용하여 가져와보면, pageParamspages 를 받게된다.

useInfiniteQuery가 API를 호출한 결과를 pages 배열 안에 갖고 있다.

페이지를 갱신하기 위해서는 getNextPageParam 함수를 호출해야 한다.
이 함수는 2개의 인자 와 함께 호출되는 데,

  • 첫 번째는, 마지막으로 fetch 한 페이지
  • 두 번째는, 지금까지 부른 모든 페이지들의 배열이다. 즉 API 로부터 받은 응답이 있는 페이지를 일컫는다.

첫 번째 인자로부터 호출되는 마지막 페이지를 사용해 볼 것이다.

그다음엔, 다음 페이지를 나타내는 숫자가 페이지의 어느 부분에 있는지의 정보를 알아야 한다. ( => pagetotal_pages 의 정보를 이용할 것이다 )
page 와 total_pages 의 정보를 이용하여 lastPage + 1total_pages 보다 큰지 확인하면 된다

코드로 확인해보자.

// api.ts
export const updateMovies = ({ pageParam }) =>
  api
    .get(`/movie/popular?api_key=${API_KEY}&page=${pageParam}`)
    .then((res) => res.data)
  • pageParam : getNextPageParam 함수의 return 값이 들어간다.
const { isLoading, isError, error, data, hasNextPage, fetchNextPage } =
  useInfiniteQuery(['movies'], updateMovies, {
    getNextPageParam: (currentPage) => {
      const nextPage = currentPage.page + 1
      return nextPage > currentPage.total_pages ? null : nextPage
    },
  })
  • hasNextPage: cursor(현재 위치)가 끝에 있는지 알려주는 함수
    • 만약 다음 페이지에 있을 때, true
  • fetchNextPage: 다음 페이지를 불러오는 함수

hasNextPage는 Boolean 값을 반환한다. hasNextPage의 값이 true일 때 fetchNextPage 함수를 실행시켜주면 infiniteQuery를 구현할 수 있다.

button 을 클릭할 때마다 fetchNextpage 함수를 실행시키도록 구현해보았다

import axios from 'axios'
import React from 'react'
import { useInfiniteQuery, useQuery } from 'react-query'
import { updateMovies } from '../utils/api'

const InfiniteQueriesPage = () => {
  const { isLoading, isError, error, data, hasNextPage, fetchNextPage } =
    useInfiniteQuery(['colors'], updateMovies, {
      getNextPageParam: (currentPage) => {
        const nextPage = currentPage.page + 1
        return nextPage > currentPage.total_pages ? null : nextPage
      },
    })

  console.log(data)

  if (isLoading) {
    return <h2>Loading...</h2>
  }

  if (isError) {
    return <h2>{error.message}</h2>
  }

  const loadMore = () => {
    if (hasNextPage) {
      fetchNextPage()
    }
  }

  return (
    <>
      <div>
        {data.pages.map((item) => {
          return item.results.map((v) => (
            <div key={v.id}>
              <h2>
                {v.id}. {v.title}
              </h2>
            </div>
          ))
        })}
      </div>
      <button onClick={loadMore}>click!</button>
    </>
  )
}

export default InfiniteQueriesPage

결과물

button 을 클릭할 때마다 fetchNextpage 함수가 실행되어, page의 숫자가 1씩 증가하여 api가 호출되는 것을 확인할 수 있다.

profile
꾸준히 새로운 것을 알아가는 것을 좋아합니다.

0개의 댓글