[리액트 쿼리] Tanstack-Query 무한 스크롤 코드

winter100·2024년 2월 9일

Tanstack-Query

목록 보기
2/2
post-thumbnail

리액트 쿼리로 무한스크롤 구현해보기

1. 사용한 라이브러리

2. 실행 흐름

    1. 첫 렌더링시 queryFn이 실행되어 initialPageParam의 값으로 데이터를 요청함
    1. 이후 <InfiniteScroll>의 scrollThreshold값 (초기0.8, 즉 화면의 80%)이 됨
    1. 80%가 되면 next={fetchNextPage} 가 실행됨
    1. fetchNextPage 는 다음 데이터를 요청하는 queryFn함수임.
    1. 이후 2번부터 반복

3. 구현 코드

import { useInfiniteQuery } from "@tanstack/react-query";
import InfiniteScroll from "react-infinite-scroll-component";

export default function InfinitePage() {


  const initalUrl = "https://swapi.dev/api/people/";

  const fetchUrl = async (url: string) => {
    const response = await fetch(url);
    return response.json();
  };

  const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery({
    // 쿼리 키, 쿼리 키가 같아야 초기화되지않고 계속해서 데이터가 쌓임
    queryKey: ["sw-people"],

    // 실제 데이터를 받아올 URL 처음엔 initialPageParam으로 받아왔다가
    // 이후 getNextPageParam의 lastPage가 전달됨
    queryFn: ({ pageParam }) => fetchUrl(pageParam),

    // 초기에 http요청할 URL
    initialPageParam: initalUrl,

    // getNextPageParam의 return 값은 다음 데이터의 URL이면 됨
    // undefined가 리턴되면 다음값이 없는 것이기 때문에 더이상 데이터를 요청하지 않음
    // 이 스타워즈 api에는 lastPage.next에 다음 페이지의 URL이 적혀있음
    // 따라서 다음 URL은 www.a.com/2, www.a.com/3, www.a.com/4 처럼 바뀌게 설정해줘야함
    getNextPageParam: (lastPage) => {
      return lastPage.next || undefined;
    },
  });
  
  /*
  -------------------------------------
  ' 예를들어 getNextPageParam의 리턴값을 "테스트" 처럼 줘버리면 '
  ' 화면의 80%높이가 돼서 다음 요청을 할때 fetchUrl함수의 url값은 "테스트"가 됨 '
        getNextPageParam: (lastPage) => {
        return "테스트"
      },
  --------------------------------------
  */
  
  if (isLoading) return <p>로딩</p>;

  return (
    <div>
      <InfiniteScroll
        dataLength={data?.pages.length}
        next={fetchNextPage}
        loader={<h2>로딩 로딩</h2>}
        hasMore={hasNextPage}
        scrollThreshold={0.8}
      >
        {data?.pages.map((item) => {
          return item.results.map((item) => (
            <li key={item.name}>{item.name}</li>
          ));
        })}
      </InfiniteScroll>

// 스크롤 할 수 있게 내용을 채워놓은 p태그
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
      <p>...</p>
    </div>
  );
}

0개의 댓글