useInfiniteQuery를 이용한 무한스크롤

이수빈·2023년 10월 25일
0

React

목록 보기
11/20
post-thumbnail

useInfiniteQuery 사용법

  • 공식문서 코드
import { useInfiniteQuery } from '@tanstack/react-query'

function Projects() {
  const fetchProjects = async ({ pageParam = 0 }) => {
    const res = await fetch('/api/projects?cursor=' + pageParam)
    return res.json()
  }

  const {
    data,
    error,
    fetchNextPage,
    hasNextPage,
    isFetching,
    isFetchingNextPage,
    status,
  } = useInfiniteQuery({
    queryKey: ['projects'],
    queryFn: fetchProjects,
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
  })

  return status === 'loading' ? (
    <p>Loading...</p>
  ) : status === 'error' ? (
    <p>Error: {error.message}</p>
  ) : (
    <>
      {data.pages.map((group, i) => (
        <React.Fragment key={i}>
          {group.data.map((project) => (
            <p key={project.id}>{project.name}</p>
          ))}
        </React.Fragment>
      ))}
      <div>
        <button
          onClick={() => fetchNextPage()}
          disabled={!hasNextPage || isFetchingNextPage}
        >
          {isFetchingNextPage
            ? 'Loading more...'
            : hasNextPage
            ? 'Load More'
            : 'Nothing more to load'}
        </button>
      </div>
      <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div>
    </>
  )
}

Props

getNextPageParam, getPreviousPageParam

  • getNextPageParam : 이 함수가 undefined를 반환하면 더이상 api 호출이 진행되지 않는다. api 호출이 남아있는 경우 Number를 리턴해야하고, 다음 페이지 number를 return 하도록 한다.

=> Number를 return하는 경우 fetchNextPage에 자동으로 pageParam을 전달한다.

Return

data

  • data객체는 query data를 포함하는 객체이다.

  • data 객체에는 pages 라는 배열과 pageParmas라는 fetching시 필요한 파라미터들을 담은 배열이 존재한다.

  • pageParmas

fetchNextPage, fetchPreviousPage

  • fetchNextPage, fetchPreviousPage 는 다음페이지, 이전페이지의 데이터를 가져오는데 사용됨.

  • fetchNextPage를 호출하면, getNextPageParam 옵션을 사용해 다음 페이지의 매개변수를 계산하고, 그 매개변수를 기반으로 새로운 페이지를 서버에서 가져옴

  • fetchPreviousPage를 호출하면, 페이지의 매개변수를 역방향으로 조정하여 이전 페이지의 매개변수를 계산하고, 그 매개변수를 기반으로 데이터를 가져옴
    (수동으로 이전, 다음데이터를 호출하도록 가능)

hasNextPage, hasPreviousPage

  • getNextPageParam이 undefined가 아닌 값을 반환한다면, hasNextPage가 true이다.

  • getPreviousParam이 undefind가 아닌 값을 반환한다면, hasPreviousPage가 true이다.

Intersection Obeserver api와 함께 사용하기

  • 웹 페이지에서 DOM 요소의 가시성 및 위치를 감시하고, 요소가 화면에 들어오거나 나갈 때 이벤트를 트리거하는 JavaScript API

  • Scroll event는 동기적으로 실행되기 때문에 메인스레드에 영향을 줌. 또한 여러 scroll event가 등록되어있을경우 이벤트가 중첩되어 호출되는 현상이 발생가능

  • Intersection Observer api는 비동기적으로 실행되기 때문에 메인스레드에 영향을 주지 않으면서 변경사항 관찰 가능함.

  • 무한스크롤이나, 페이지 스크롤시 이미지를 Lazy Loading 하는데 사용가능함.

사용법

  • Intersection Observer 객체 생성

  • IntersectionObserverCallback: IntersectionObserverCallback은 관찰된 요소의 상태가 변경될 때 호출되는 콜백 함수입니다. 이 콜백 함수는 두 개의 매개변수를 받습니다

  • entries 및 observer.

  • entries는 IntersectionObserverEntry 객체의 리스트임.

  • observer는 생성한 인스턴스를 참조함.

const observer = new IntersectionObserver(callback, options);

function callback(entries, observer) {
  entries.forEach((entry) => {
    // entry.intersectionRatio를 통해 가시성 정보 확인
    if (entry.isIntersecting) {
      // 요소가 화면에 들어옴
    } else {
      // 요소가 화면을 벗어남
    }
  });
}

options

  • root : 교차영역의 기준이 될 root 엘리먼트. observe의 대상으로 등록할 엘리먼트는 반드시 root의 하위요소여야만함. (default : null, 브라우저 viewport)

  • rootMargin : default : '0px 0px 0px 0px' => root element마진값.

  • threshold : 0 ~ 1 사이의 숫자혹은 이 숫자들의 배열. 타깃 엘리먼트에 대한 교차비율을 의미함. 0이라면, 타깃 엘리먼트가 교차영역에 진입했을때 observer를 실행, 1이라면 타깃 전체가 들어왔을 때 observer를 실행

Method

  • observe : 타겟에 대한 관찰을 시작할 때 사용함

  • unobserve : 타깃에 대한 관찰을 멈출 때 사용함.

  • disconnect : 전체 다수 엘리먼트에 대한 관찰을 멈출때 사용

  • takeRecords : IntersectionObserverEntry 배열반환.

활용방법

  • 콜백함수에서 isIntersecting을 감지 후, fetchNextPage 함수를 통해 직접 api를 호출하는 방식으로 무한스크롤을 구현 가능하다.

ref) 공식문서 :https://tanstack.com/query/v4/docs/react/guides/infinite-queries

Intersection Observer api
: https://blog.hyeyoonjung.com/2019/01/09/intersectionobserver-tutorial/

mdn : https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

profile
응애 나 애기 개발자

0개의 댓글