[React-Query] 리액트 쿼리로 무한스크롤 구현하기

제론·2022년 9월 11일
3

#React

목록 보기
10/11

StarWars Infinity Scroll

useInfiniteQuery()

  • 다음 쿼리 추적
    • 쿼리 결과로 데이터 이외의 페이지 관련 쿼리가 return됨
    • 이전 쿼리와 다음 쿼리, 전체 페이지 수를 알려줌
  • react-qeury 개발자도구는 node 노드 환경이 production이 아닐때만 실행됨
    • 즉 개발모드일 때만 실행됨
  • useQuery()와의 차이
    • 반환된 데이터 프로퍼티 형식이 다름 2개의 프로퍼티를 가지는 객체
      • pages - 해당 페이지의 객체 배열 쿼리 값
      • pageParams - 각 페이지의 매개변수가 기록되어 있음 - 잘 사용하지 않음
  • 무한스크롤 작동 원리
 useInfiniteQuery("sw-people", ({pageParam = defaultUrl}) => fetchUrl(pageParam))
- pageParam이 fetchUrl의 매개변수로 들어가 적절한 페이지를 가져옴
- pageParam의 현재값은 유지됨!
- getNextPageParam이 다음 페이지에 대한 url을 가져오고 그 값이 pageParam에 할당됨
  • useInfiniteQuery() 옵션
    • getNextPageParam: (lastPage, allPages)
      • pageParam을 업데이트 시킴
      • lastPage, allpages
  • 호출 방식
    • fetchNextPage() - 사용자가 더 많은 데이터를 요청할 때 호출
    • hasNextPage()
      • getNextPageParam의 반환 값을 기반으로 함, 마지막 쿼리의 데이터를 어떻게 사용할지 지시
      • pageParam이 정의되어 있으면 참, 아니면 거짓
    • isFetchingNextPage() - 다음페이지를 가져오는지 혹은 일반적인 fetching인지 구분
  • isFeching을 통해 데이터를 받아오기 전 무언가를 표시할 때 → 데이터를 받아온다면 스크롤이 위로 올라간다
    • 그 이유는 새로운 페이지를 열어야 할 때 조기 반환이 실행되기 때문!
    • isFetching을 통해 가져올 동안 표시할 수 있음!
// 무한스크롤 예시 코드
import InfiniteScroll from 'react-infinite-scroller'
import { Person } from './Person'

import { useInfiniteQuery } from 'react-query'

const initialUrl = 'https://swapi.dev/api/people/'
const fetchUrl = async (url) => {
  const response = await fetch(url)
  return response.json()
}

export function InfinitePeople() {
  const { data, fetchNextPage, hasNextPage, isLoading, isFetching, isError, error } = useInfiniteQuery(
    'sw-people',
    ({ 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) =>
          pageData.results.map((person) => {
            return (
              <Person key={person.name} name={person.name} hairColor={person.hair_color} eyeColor={person.eye_color} />
            )
          })
        )}
      </InfiniteScroll>
    </>
  )
}
  • useInfiniteQuery() 함수 호출

  • 인수로 키값과, pageParam, getNextPageParam을 입력한다.

  • pageParam은 호출할 페이지 url이고 getNextPageParam은 지난 페이지에서 다음 페이지의 값을 pageParam에 넣어준다. 값이 없을 경우 undefined를 할당하여 다음 페이지가 없다는 걸 명시한다.

  • InfiniteScroll 컴포넌트 loadMore에는 fetchNextPage, hasMore에는 hasNextPage를 할당한다

  • fetchNextPage는 값이 더 필요할 때 작동하는 함수이고 hasNextPage는 다음 페이지가 있는지 확인한다.

  • useInfiniteQuery()의 결과로 나오는 data는 pages라는 데이터가 별도로 있고 pages를 매핑하며 뿌려주어야한다.

  • 각각 페이지를 다시 매핑하는 형식으로 데이터를 화면에 뿌려준다.

profile
Software Developer

0개의 댓글