React Native

useInfiniteQuery + Firestore

방피터 2022. 5. 26. 11:59

React Query에서 나름 강력크한 기능 중 하나가 infiniteQuery지.

Flatlist로 무한 스크롤 같은 거 구현할 때 데이터를 계속 읽어와야 하잖아. 그럴 때 useInfiniteQuery를 사용해서 연속적으로 데이터를 읽어와. 무한 스크롤 안들어간 앱 찾기가 힘드니까 거의 필수라고 볼 수 있지. Query할 DB는 다른 건 열심히 안해봤고 Firestore는 지금 사용중인데 잘 돌아가네.

 

useInfiniteQuery 원래 문서는 아래 링크에 있으니까 참고해

https://react-query.tanstack.com/reference/useInfiniteQuery

 

useInfiniteQuery

Subscribe to Bytes Your weekly dose of JavaScript news. Delivered every Monday to over 80,000 devs, for free.

react-query.tanstack.com

 

그럼 먼저 useInfiniteQuery 사용법을 한 번 보자구. useInfiniteQuery 사용하기 위해서는 1. Query 변수, 2. Query 함수, 3. 다음 페이지 번호 가져오는 함수 이렇게 최소 3가지가 필요해. 아래 코드를 대강 살펴보자고~

const cardQuery = useInfiniteQuery(
    ["pokemonCard"], //1. 쿼리 변수!!!!!!!!!
    async ({queryKey, pageParam}) => { //2. 쿼리 함수!!!!!!!!!
      return pageParam ? //PageParam 이 있다면
        firestore()
          .collection("pokemonCard") // pokemonCard 컬렉션에서
          .orderBy("createdAt","desc") // createdAt 내림차순으로 정렬하고
          .startAfter(pageParam) //pageParam 부터 가져오는데
          .limit(25) // 25개만 가져오도록 제한하고
          .get()
          .then((querySnapshot) => querySnapshot)
        : firestore() //pageParam이 없으면 첫 Query!
          .collection("pokemenCard")
          .orderBy("createdAt","desc") // createdAt 내림차순으로 정렬하고
          .limit(25) // 25개만 가져오도록 제한하고
          .get()
          .then((querySnapshot) => querySnapshot)
    }, 
    {
      getNextPageParam: (querySnapshot) => { //3. 다음 페이지 번호 가져오는 함수!!!!!!!!!
        if (querySnapshot.size < 25) return null;
        //가져온 스냅샷 갯수가 25개 보다 작다는 의미는 끝까지 다 읽은거라 다음 페이지가 없다(null) 반환!
        else return querySnapshot.docs[querySnapshot.docs.length - 1];
        //아니면 가져온 문서의 마지막을 NextPage 파라미터로 돌려줌.
      },
    }
  );

간단히 설명하자면 useInfiniteQuery는 getNextPageParam로 다음에 가져올 페이지 파라미터를 Query 함수로 전달해. 페이지 파라미터를 전달받은 Query 함수가 적절하게 데이터를 읽어오면 끝! 여기서 주의할 건 Query 함수에 전달할 페이지 파라미터만 신경써주는 것임.

 

https://firebase.google.com/docs/firestore/query-data/query-cursors?hl=ko#web-version-9_3 

 

쿼리 커서로 데이터 페이지화  |  Firebase Documentation

Check out what’s new from Firebase at Google I/O 2022. Learn more 의견 보내기 쿼리 커서로 데이터 페이지화 Cloud Firestore의 쿼리 커서를 사용하면 쿼리에 정의한 매개변수에 따라 쿼리에서 반환하는 데이터를

firebase.google.com

Firestore는 startAfter(), startAt(), endBefore(), endAt() 요런 걸로 pagination(페이지화)하는데 얘네들은 documentSnapshot을 cursor(커서)로 사용해. startAfter(documentSnapshot) 하면 documentSnapshot 다음 문서에 커서를 두고 읽어올 수 있어. 그래서 getNextPageParam에서 뭉탱이로 읽어온 querySnapshot(문서 뭉탱이)의 마지막 문서를 파라미터로 전달하는 거지. 이건 DB 종류나 사용하는 API에 따라서 달라지니까 맞춰서 하면 돼.

 

 

그리고 다음 페이지 불러올 땐 아래 코드처럼 간단하게 fetchNextPage() 메서드 사용하면 되고

const fetchMore = () => {
    if (cardQuery.hasNextPage) {
      cardQuery.fetchNextPage();
    } else {
      if (__DEV__) console.log("no next page");
    }
  };

 

그리고 Flatlist에서는 아래 코드처럼 onEndReached 에 다음 페이지 읽어오는 함수 물려주면 되고

<FlatList
   ...
   onEndReached={loadMore}
   ...
/>

이게 한번 익숙해지면 쉬운데 그 전까지는 조금 헤깔리는 게 있어. React Query 문서도 뭐랄까 조금 불친절하고 그래서 ㅎㅎㅎ 내가 맘속 깊이 영어를 배척하는 것일지도 ㅋㅋㅋㅋㅋ

 

React native하면서 Flatlist + useInfiniteQuery 는 거의 뭐 필수니까 꼭 익숙해지길 바래~~

반응형