Just Do IT!
[React Native] 무한 스크롤(Infinite Scrolling) 적용하기 본문
728x90
무한 스크롤이란?
- 스크롤이 기존 렌더링된 리스트 마지막 부분 또는 그 근처에 도달했을 때 새로운 리스트를 추가로 더 불러오는 인터랙션
- FlatList의 onEndReached props를 이용하여 스크롤이 리스트의 마지막 부분에 도달했을 때 trigger 되었을 때 추가로 fetch 처리한다
- 기존의 배열 리스트에 추가로 불러온 배열을 합쳐셔 리렌더링하는 방식으로 구현된다
- React-Query의 useInfiniteQuery 를 사용하면 간편하게 무한스크롤 구현이 가능하다
React-Query의 useInfiniteQuery 적용
const {
fetchNextPage, // 다음 페이지 fetch
hasNextPage, // 다음 페이지가 존재하는지 true/false
isFetchingNextPage, // 다음 페이지를 fetching 중인지 true/false
data // { pageParams: [ undefined, 2, 3, ... ], pages: [ {}, {}, {}, ... ] }
} = useInfiniteQuery(queryKey, ({ pageParam = 1 }) => fetchPage(pageParam), {
getNextPageParam: (lastPage) => {
if(lastPage.page < lastPage.total_page) {
return lastPage.page + 1;
}
}
})
// 컴포넌트 마운트(최초렌더링) 시 fetcher 함수가 바로 실행
// fetchNextPage 실행 시 getNextPageParam 실행 후 fetcher 함수 실행
- 무한스크롤을 위한 hook이다
- 인자로 queryKey, fetcher 함수, 옵션 객체를 받는다
- fetcher 함수에 매개변수로 pageParam을 넘겨 받는다 (pageParam이 1이면 fetch 요청을 하는 것)
- getNextPageParam에서 lastPage 값이 전체 페이지의 값보다 작으면 lastPage + 1을 return (다음 페이지 요청)
- 이런 방식으로 기존 배열 리스트에 추가로 불러온 배열을 합친다.
적용 예시
// Movies.jsx
import { useInfiniteQuery, useQuery, useQueryClient } from "react-query";
...
const {
data: topRatedData,
isLoading: isLoadingTR,
fetchNextPage: fetchNextPageTR,
hasNextPage: hasNextPageTR,
} = useInfiniteQuery(["Movies", "TopRated"], getTopRated, {
getNextPageParam: (lastPage) => {
if (lastPage.page < lastPage.total_pages) {
return lastPage.page + 1;
}
},
});
const {
data: upComingData,
isLoading: isLoadingUC,
fetchNextPage,
hasNextPage,
} = useInfiniteQuery(["Movies", "UpComing"], getUpcoming, {
getNextPageParam: (lastPage) => {
// 다음 페이지가 있으면 +1
if (lastPage.page < lastPage.total_pages) {
return lastPage.page + 1;
// return 값이 page params로 넘어감
}
},
});
...
// infinity scroll
// upcoming scroll
const fetchMore = async () => {
// fetch next page
if (hasNextPage) {
await fetchNextPage();
}
};
// top rated scroll
const fetchMoreTR = async () => {
if (hasNextPageTR) {
await fetchNextPageTR();
}
};
...
return (
...
// 누적되어지는 1차 영화 리스트 (무한 스크롤 적용)
data={upComingData.pages.map((page) => page.results).flat()}
renderItem={({ item }) => <UpComing movie={item} />}
keyExtractor={(item) => item.id}
ItemSeparatorComponent={<View style={{ height: 15 }} />}
/>
);
}
- useInfinityQuery에서 return 해주는 data 값 중에서 results가 필요하다
- 이를 위해 map을 사용해 results에 접근하는데 이 results는 2차원 배열이므로 1차원 배열로 변경해야 한다. (flat 사용)
기타 자세한 정보들은 공식문서에서 정확히 알아두기.
https://react-query-v3.tanstack.com/reference/useInfiniteQuery
728x90
'개발 공부 > React Native' 카테고리의 다른 글
[React Native] useMutation 이용해서 수정/삭제 기능 구현하기 (0) | 2023.01.05 |
---|---|
[React Native] react-query 이용하기 (0) | 2023.01.05 |
[React Native] ScrollView 대신 FlatList 사용하기 (0) | 2023.01.04 |
[React Native] 영화 정보 API 사용하기 (TMDB) (0) | 2023.01.04 |
[React Native] react-navigation (0) | 2023.01.03 |