React Query Infinite , useInfiniteQuery 쉽게 사용하자

신대현·2023년 3월 26일
3

react-query

목록 보기
1/1
post-thumbnail

안녕하세요. 최근에 이직을 하게 되면서 react-query를 접할 일이 생겼는데 기존에 사용하던 SWR과 비슷하여 그중에서 useInfiniteQuery공식 홈페이지 예제를 보자마자 🤮PTSD가 왔습니다.
useSWRInfinite 만큼은 아니었지만 인피니티 스크롤 기능 하나 때문에 예제처럼 많은 코드를 쓰기는 싫었기 때문에 모듈화를 하여 개선해 보려고 합니다.

결론부터 말씀드리자면 react-query-infinite-scroll 을 사용하시면 됩니다.

그렇습니다. 사실 라이브러리를 흥보 하고 싶었습니다.😁
어떻게 개선되는지 보겠습니다.

기본 예제

// IO Custom Hooks
const useOnScreen = (ref, rootMargin = "0px") => {
  // State and setter for storing whether element is visible
  const [isIntersecting, setIntersecting] = useState(false);
  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        // Update our state when observer callback fires
        setIntersecting(entry.isIntersecting);
      },
      {
        rootMargin,
      }
    );
    if (ref.current) {
      observer.observe(ref.current);
    }
    return () => {
      observer.unobserve(ref.current);
    };
  }, []); // Empty array ensures that effect is only run on mount and unmount
  return isIntersecting;
}

// Example
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,
    status,
  } = useInfiniteQuery({
    queryKey: ['projects'],
    queryFn: fetchProjects,
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
  })
  
  const ref = useRef()
  const isIntersecting = useOnScreen(ref);

  useEffect(()=>{
    if(isIntersecting){
      fetchNextPage()
    }
  },[isIntersecting])
  
  if(status === 'loading'){
    return <p>Loading...</p>
  }
  
  if(status === 'error'){
    return <p>Error: {error.message}</p>
  }
  return (
    <>
      {data.pages.map((group, i) => (
        <React.Fragment key={i}>
          {group.projects.map((project) => (
            <p key={project.id}>{project.name}</p>
          ))}
        </React.Fragment>
      ))}
      <div ref={ref}></div>
    </>
  )
}

react-query-infinite-scroll

Install

yarn add react-query-infinite-scroll

npm i react-query-infinite-scroll

pnpm i react-query-infinite-scroll

설치 부터 해줍시다

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

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

const query = useInfiniteQuery<TValue>(
  ["list"],
  fetchProjects,
  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
);


<QueryInfiniteScroll<TValue>
  query={query}
  loading={<div>loading</div>}
  error={<div>error</div> || (error)=> <div>{error}</div>}
  observer={<div>loading</div>}
  >
  {(res) => {
    return res?.data.map((data, idx) => <div key={idx}>{data._id}</div>);
  }}
</QueryInfiniteScroll>

Props

  • query - useInfiniteQuery의 반환 값을 넣어주시면 되겠습니다.
  • loading - 캐싱된 데이터가 없고 data fetch중 로드 중인 경우 대체할 컴포넌트를 넣어주시면 되겠습니다
  • error - 쿼리 시도를 실패 하거나 data fetch가 로드 중 실패 한 경우 대체할 컴포넌트를 넣어주시면 되겠습니다
  • observer - 스크롤 아래의 삽입이 될 컴포넌트를 넣어주시면 되겠습니다.

React-Query V3

react-query v3 도 v4와 동일한 반환값을 가지고 있기 때문에 동일하게 사용 가능합니다

결론

제발🙏 사용해주시면 감사하겠습니다...
끝입니닷

profile
프론트엔드 개발자 입니다

1개의 댓글

comment-user-thumbnail
2일 전

좋은 글 감사합니다! 무한스크롤 구현할 때 꼭 사용해봐야겠네요

답글 달기