일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- node.js
- coding
- JS
- HTML
- TypeScript
- 그럼에도 불구하고
- max-width
- 프론트엔드
- 코딩테스트
- 코드업
- java
- 자바
- 그럼에도불구하고
- redux
- 반응형 페이지
- 변수
- Servlet
- media query
- @media
- 자바문제풀이
- frontend
- node
- webpack
- CSS
- react-router-dom
- cleancode
- github
- git
- react
- JavaScript
- Today
- Total
그럼에도 불구하고
[React Query] useInfiniteQuery와 Infinite Scroll 본문
useInfiniteQuery와 Infinite Scroll에 대해 알아보겠습니다.
🧑🏻💻 useInfiniteQuery
기존 데이터를 모두 불러왔을 때, 더 많은 데이터를 아래에 불러오는 "무한 스크롤"은 매우 흔한 UI 패턴입니다.
Tanstack Query는 이런 리스트형 데이터를 요청하기 위해, useQuery의 유용한 버전인 useInfiniteQuery를 지원합니다.
즉, useInfiniteQuery는 파라미터 값만 변경하여 동일한 useQuery를 무한정 호출할 때 사용합니다.
useInfiniteQuery는 전반적으로 useQuery와 동일하지만, useInfiniteQuery와 useQuery의 차이를 비교하며 useInfiniteQuery의 기능을 살펴보겠습니다.
📌 반환 객체에서 반환된 데이터 프로퍼티의 형태 차이
useQuery에서의 데이터는 단순히 쿼리함수에서 반환된 데이터를 말합니다.
반면, useInfiniteQuery는 두 개의 프로퍼티를 가지고 옵니다.
첫 번째는 데이터 페이지 객체의 Array 페이지이고, 이때 각 페이지에 있는 각 요소가 바로 useQuery를 통해 받아오는 데이터들입니다.
두 번째는 각 페이지의 매개변수가 기록되는 pageParam입니다. pageParam는 검색된 쿼리의 키를 추적하기 때문입니다. 모든 쿼리는 페이지 배열에 고유한 요소를 가지고 있고, 그 요소는 해당 쿼리에 대한 데이터에 해당합니다. 따라서 페이지가 진행되면서 쿼리도 변하게 됩니다.
⭐️ pageParam은 useInfiniteQuery가 현재 어떤 페이지에 있는지 확인할 수 있는 파라미터 값입니다.
📌 useInfiniteQuery의 옵션
- ⭐️ getNextPageParam
- 다음 페이지로 가는 방식을 정의하는 함수입니다.
- 마지막 또는 모든 페이지에 대한 데이터를 다룹니다.
- 다음 api를 요청할 때 사용될 pageParam값을 정할 수 있습니다.
- ⭐️ fetchNextPage
- 사용자가 더 많은 데이터를 요청할 때 호출하는 함수입니다.
- ⭐️ hasNextPage
- getNextPageParam의 반환 값을 기반으로 하는 함수입니다.
- 마지막 쿼리의 데이터를 어떻게 사용할지 지시합니다.
- undefined의 경우 더 이상 데이터가 없다는 뜻으로 가져올 데이터가 없음을 나타냅니다.
- ⭐️ isFetchingNextPage
- 다음 페이지를 가져오는 건지, 일반적인 fetching인지를 구별합니다.
https://tanstack.com/query/v4/docs/react/reference/useInfiniteQuery
🔄 흐름도 (Flow)
1. ⭐️ Component Mount
이 시점에서는 useInfiniteQuery이 반환된 객체의 data 프로퍼티가 아직 정의되어 있지 않습니다. ( 아직 Query가 만들어지지 않았기 때문)
const { data ... } = useInfiniteQuery( ... );
👉 data : undefined
2. ⭐️ Fetch first page
useInfiniteQuery은 쿼리 함수를 사용하여 첫 페이지를 가져옵니다.
이때 쿼리함수는 useInfiniteQuery의 첫 번째 인수이고, pageParam을 인수로 받습니다.
const { data, ... } = useInfinteQuery([key], { pageParam = initialUrl } => function(pageParam), ... )
👉 data.pages[0] : {...} // 첫 번째 페이지
👉 pageParam : initialUrl (default)
3. ⭐️ getNextPageParam update pageParam
데이터가 반환된 후 React Query가 getNextPageParam을 실행하고, getNextPageParam이 pageParam을 업데이트합니다.
// 이때는 API에서 반환된 데이터양식에 따라 lastPage, Allpage를 고르면 됩니다.
getNextPageParam: (lastPage, allPage) => ...
const { data } = useInfiniteQuery(
[key],
({ pageParam = initialUrl }) => function(pageParam),
{
getNextPageParam: (lastPage) => ...
}
);
4. ⭐️ hasNextPage?
React Query가 hasNextPage의 값을 결정하는 방식은 pageParam이 정의되어 있는지 아닌지에 따릅니다. 즉, 다음으로 올 페이지의 유무에 따라 함수가 사용됩니다.
5. ⭐️ yes -> (use scrolls or clicks button) fetchNextPage
사용자가 스크롤하거나 버튼을 클릭하는 등의 fetchNextPage를 트리거할 만한 행동을 했다면 다음 요소를 업데이트하거나 페이지 배열에 다음 요소를 추가합니다.
그 후에 다시 3번으로 돌아가서 같은 작업을 실행합니다.
6. ⭐️ no -> done
fetchNextPage를 트리거 할 만한 행동이 없다면 이대로 종료합니다.
🧑🏻💻 React Infinite Scroller
이 패키지는 창과 스크롤 가능한 요소를 모두 지원하여 간단하고 가벼운 무한 스크롤 페이지 또는 요소를 만들 수 있게 해 줍니다. 무엇보다 useInfiniteQuery와 호환이 잘 됩니다.
📌 loadMore : 데이터가 더 필요할 때 불러와 useInfiniteQuery의 fetchNextPage 함숫값을 이용합니다.
📌 hasMore : hasNextPage와 같이 useInfiniteQuery에서 나온 객체를 해체한 값을 이용합니다.
예시 코드
import InfiniteScroll from "react-infinite-scroller";
import { useInfiniteQuery } from "@tanstack/react-query";
import { Species } from "./Species";
const initialUrl = "https://swapi.dev/api/species/";
const fetchUrl = async (url) => {
const response = await fetch(url);
return response.json();
};
export function InfiniteSpecies() {
const {
data,
fetchNextPage,
hasNextPage,
isLoading,
isFetching,
isError,
error,
} = useInfiniteQuery(
["sw-species"],
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam: (lastPage) => lastPage.next || undefined,
}
);
if(isLoading) {
return <div className="loading">Loading...</div>;
}
if(isError) {
return <div>Error! {error.toString()}</div>;
}
return (
<>
{isFetching && <div className="loading">Loading...</div>}
<InfiniteScroll loadMore={fetchNextPage} hasMore={hasNextPage}>
{data.pages.map((pageData) => {
return pageData.results.map((species) => {
return <Species
key={species.name}
name={species.name}
language={species.language}
averageLifespan={species.average_lifespan}
/>
})
})}
</InfiniteScroll>
</>
);
}
여기서 무한 스크롤 컴포넌트는 스스로 페이지의 끝에 도달했음을 인식하고 fetchNextPage를 불러오는 기능을 수행합니다. 😊
🏷️ 출처
https://velog.io/@pjh1011409/React-Query-Prefetching-Pagination
https://www.npmjs.com/package/react-infinite-scroller
https://velog.io/@cnsrn1874/react-query-useInfiniteQuery
'React > React query' 카테고리의 다른 글
[React Query] isLoading과 isFetching은 헷갈려 (0) | 2023.10.19 |
---|---|
[React Query] 페이지네이션(Pagination)과 데이터 프리페칭(Prefetching) (1) | 2023.10.18 |
[React Query] React Query를 TypeScript로 사용할 때 Type 지정 (0) | 2023.10.14 |
[React Query] React Query에 대하여 (0) | 2023.08.24 |