무한 스크롤을 수행하기 위해 무한 쿼리(TanStack 쿼리)를 사용하는 방법

Mary-Kate Olsen
풀어 주다: 2024-11-10 10:01:02
원래의
581명이 탐색했습니다.

다음은 귀하의 게시물을 영어로 번역한 것입니다.


이 게시물에서는 TanStack 쿼리, 특히 Infinity 쿼리를 사용하여 무한 스크롤을 구현하는 방법을 알려 드리겠습니다. Vite로 사진 피드를 만들고 무한 스크롤을 설정하겠습니다. 시작하려면 터미널을 열고 다음 명령을 실행하여 기본 구성으로 프로젝트를 복제하세요.

git clone --branch start https://github.com/DAVI-REZENDE/photos-feed.git

cd photos-feed
npm i
로그인 후 복사

모든 준비가 완료되었습니다! 이제 TanStack 쿼리 라이브러리를 사용하여 무한 스크롤 기능을 구현해 보겠습니다. 아래 명령으로 설치하세요.

npm i @tanstack/react-query
npm i axios
로그인 후 복사

App.tsx 파일에서 코드가 다음과 같은 것을 볼 수 있습니다.

How to use Infinity Queries (TanStack Query) to do infinite scrolling

먼저 useEffect를 무한 요청 관리를 담당하는 후크인 useInfiniteQuery로 대체하겠습니다. 다음과 같이 queryKey 및 queryFn이라는 두 가지 속성을 제공해야 합니다.

const { 
  data, 
  isLoading,
  fetchNextPage,
  isFetchingNextPage, 
  isFetching, 
  hasNextPage 
} = useInfiniteQuery({
    queryFn: fetchPhotos,
    queryKey: ['photos'],
    initialPageParam: 1,
    getNextPageParam: (lastPage) => {
      return lastPage.nextPage
    }
})
로그인 후 복사

각 매개변수에 대한 설명:

  • queryFn: 요청 데이터 반환을 담당하는 함수입니다. 현재 페이지를 매개변수로 받습니다.
  • queryKey: 요청에 대한 식별자 역할을 하며 종속성 배열 역할도 합니다. 전달한 변수가 변경될 때마다 useInfiniteQuery가 자동으로 다시 가져옵니다.
  • initialPageParam: 초기 기본값입니다.
  • getNextPageParam: queryFn 함수가 반환하는 모든 것을 수신하고 요청할 다음 페이지 번호를 반환해야 합니다.

fetchPhotos 기능을 수정해야 합니다.

async function fetchPhotos({ pageParam }: { pageParam: number }) {
  const response = await api.get<ImageData[]>('/photos', {
    params: {
      page: pageParam,
      per_page: 5,
    }
  })

  return {
    data: response.data,
    nextPage: pageParam + 1
  }
} 
로그인 후 복사

useInfiniteQuery 후크는 페이지 단위로 데이터를 반환하므로 렌더링이 약간 변경됩니다.

<main className="h-screen w-screen bg-zinc-950 flex flex-col gap-6 p-6 items-center text-white overflow-auto">
  {isLoading ? 'Loading...' : (
    <>
      {data?.pages.map((group, i) => (
        <div className="flex flex-col gap-6" key={i}>
          {group.data.map(({ id, urls }) => (
            <img className="aspect-square rounded-md h-[550px] object-cover" src={urls.regular} key={id} />
          ))}
        </div>
      ))}
      <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>
    </>
  )}
</main>
로그인 후 복사

이제 사용자가 스크롤 끝에 도달하여 '더 보기' 버튼을 클릭할 때마다 데이터가 자동으로 추가됩니다.

사용자가 버튼을 클릭할 필요 없이 스크롤 끝에 도달할 때마다 다음 페이지를 가져오려면 다음 함수를 추가하세요.

function handleScroll(event: UIEvent<HTMLElement>) {
  const { scrollTop, clientHeight, scrollHeight } = event.currentTarget

  if (scrollTop + clientHeight >= scrollHeight) {
    fetchNextPage()
  }
}
로그인 후 복사

목록을 래핑하는 div에 onScroll 이벤트를 추가하고 거기에서 함수를 호출하세요. 완료! 이제 사용자가 끝까지 스크롤할 때마다 새로운 데이터가 자동으로 로드됩니다.

결국 코드는 다음과 같습니다.

import { useInfiniteQuery } from "@tanstack/react-query"
import { UIEvent } from "react"
import { api } from "./lib/api"

type ImageData = {
  id: string,
  urls: {
    regular: string
  }
}

export function Home() {
  async function fetchPhotos({ pageParam }: { pageParam: number }) {
    const response = await api.get<ImageData[]>('/photos', {
      params: {
        page: pageParam,
        per_page: 5,
      }
    })

    return {
      data: response.data,
      nextPage: pageParam + 1
    }
  } 

  const { data, isLoading, fetchNextPage, isFetchingNextPage, isFetching, hasNextPage } = useInfiniteQuery({
    queryFn: fetchPhotos,
    queryKey: ['photos'],
    initialPageParam: 1,
    getNextPageParam: (lastPage) => {
      return lastPage.nextPage
    }
  })

  function handleScroll(event: UIEvent<HTMLElement>) {
    const { scrollTop, clientHeight, scrollHeight } = event.currentTarget

    if (scrollTop + clientHeight >= scrollHeight) {
      fetchNextPage()
    }
  };


  return (
    <main className="h-screen w-screen bg-zinc-950 flex flex-col gap-6 p-6 items-center text-white overflow-auto" onScroll={handleScroll}>
      {isLoading ? 'Loading...' : (
        <>
          {data?.pages.map((group, i) => (
            <div className="flex flex-col gap-6" key={i}>
              {group.data.map(({ id, urls }) => (
                <img className="aspect-square rounded-md h-[550px] object-cover" src={urls.regular} key={id} />
              ))}
            </div>
          ))}
          <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>
        </>
      )}
    </main>
  )
}
로그인 후 복사

감사합니다!

위 내용은 무한 스크롤을 수행하기 위해 무한 쿼리(TanStack 쿼리)를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿