Just Do IT!

[React Native] 무한 스크롤(Infinite Scrolling) 적용하기 본문

개발 공부/React Native

[React Native] 무한 스크롤(Infinite Scrolling) 적용하기

MOON달 2023. 1. 5. 19:55
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

 

useInfiniteQuery | TanStack Query Docs

const { fetchNextPage,

tanstack.com