리액트 React/ReactQuery

3. useInfiniteQuery

leexx 2023. 5. 18. 19:38

useInfiniteQuery

  • useInfiniteQuery = 몇몇 인자들이 추가된 useQuery
  • 파라미터 값만 변경하여 동일한 useQuery 를 여러번 호출할 때 사용 => Infinite Scroll, Pagination 에 사용 가능

 

useInfiniteQuery 의 인자들 (Request)

  • useQuery 에서도 사용한 인자들
    • queryKey
    • queryFn
      • ({pageParam = initialUrl}) => fetchUrl(pageParam)
        • pageParam 은 고정
        • pageParam 에, 다음에 요청할 정보를 넣어줌, url 이 될 수도 있고 page(숫자)가 될 수도 있음
        • API 에서 다음 요청 으로 주는 정보가 무엇이냐에 따름
  • (new) useInfiniteQuery 의 인자들 (옵션)
    • getNextPageParam
      • getNextPageParam: (lastPage, allPages) => { return lastPage.next; }
        • next page 를 받아서 useInfiniteQuery 에게 전달해줌 (?), 따라서 요 옵션이 없으면 next page 정보 못불러옴
        • allPages 는 옵션, allPages 에는 여태까지 fetch 해온 모든 페이지들이 배열로 누적되어있음
    • getPreviousPageParam
      • getPreviousPageParam: (firstPage, allPages) => { return firstPage; }
        • firstPage 에는 첫 번째 요청한 페이지의 정보가, allPages 에는 마찬가지로 모든 페이지들이 배열로 누적되어있음
        • 이 때 firstPage 에는 완전 최초의 요청이 아닌, 두 번째 요청부터 들어감

 

useInfiniteQuery 의 인자들 (Response)

  • isFetching, isLoading, isError, error, data
  • hasNextPage
    • Boolean, 다음 페이지가 있는지 여부를 반환
  • fetchNextPage
    • 함수, 다음에 fetch 할 함수
const {data, isFetching, isLoading, isError, error, hasNextPage, fetchNextPage} = useInfiniteQuery(
        ['species'],
        ({pageParam = initialUrl}) => fetchUrl(pageParam),
        {
            getNextPageParam: (lastPage) => lastPage.next,
        }
    )

 

무한스크롤 적용 (/w react-infinite-scroller)

import InfiniteScroll from "react-infinite-scroller";
import {Species} from "./Species";
import {useInfiniteQuery} from "@tanstack/react-query";
import axios from "axios";

const initialUrl = "https://swapi.dev/api/species/";
const fetchUrl = async (url) => {
    const response = await axios.get(url);
    return response.data;
};

export function InfiniteSpecies() {
    // TODO: get data for InfiniteScroll via React Query
    const {data, isFetching, isLoading, isError, error, hasNextPage, fetchNextPage} = useInfiniteQuery(
        ['species'],
        ({pageParam = initialUrl}) => fetchUrl(pageParam),
        {
            getNextPageParam: (lastPage) => lastPage.next,
        }
    )

    if (isError) return <div className="loading">Error <p>{error.toString()}</p></div>
    if (isLoading) return <div className="loading">isLoading</div>

    return (
        <>
            {isFetching && <div className="loading">Fetching</div>}
            <InfiniteScroll hasMore={hasNextPage} loadMore={fetchNextPage}
            > {
                    data.pages.map((pageData) => pageData.results.map((species) => <Species
                        key={species.name}
                        name={species.name}
                        language={species.language}
                        averageLifespan={species.average_lifespan}/>))
            }
            </InfiniteScroll>
        </>
    )
}

 

참고