본문 바로가기
Clozet [프로젝트]

[React] useInfiniteQuery를 사용한 무한스크롤 구현

by ungyuun 2023. 10. 14.

 

요즘 서비스에서는 페이징 기법으로 페이지를 이동하는것보다, 페이지를 내려 새로운 리소스를 가져오는 무한스크롤 기반의 페이지가 많다. UX쪽 측면으로 1페이지, 2페이지 이동하는 것보다 하단으로 스크롤을 내려 페이지를 이동하는것이 편하기 때문이다. 또한 모든 데이터를 로드하면 랜더링이 느려지기 때문에 부분부분 필요한 데이터를 호출해야한다.

 

프로젝트에 무한스크롤을 적용하려고 한다. 무한스크롤에서 특정 위치에서 데이터를 로드하기 위해 useInView 훅을 사용하려고 한다. useInView 훅은 컴포넌트의 inView 상태를 모니터링해주는 훅이다. 요소가 뷰포트에 진입/제외 되는 시점을 파악시켜준다. (react-intersection-observer)

 

다음 무한페이징을 구현하기위해 useInfiniteQuery 훅을 사용했다. useInfiniteQuery훅은 페이징된 데이터를 관리하고 캐싱하기 위해 사용된다. REST API를 통해 데이터를 비동기적으로 가져와 쿼리 결과를 관리하는 데 효과적이다. 

다음은 InfiniteQuery의 문서이다. (useInfiniteQuery

 

data: 쿼리로부터 받은 데이터

status: 쿼리 상태를 나타냄. loading", "error " "success" 가 있음.

fetchNextPage: 다음 페이지를 가져오는 함수

hasNextPage: 가져올 다음 페이지가 있는지 알려주는 불리언 값

isFetchingNextPage: 다음 페이지를 가져오는 동안 true인 불리언 값.

const [ref,inView] = useInView();

const { data, status, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useInfiniteQuery("products", ({ pageParam = 0 }) => getProduct(pageParam), {
      select: data => ({
        pages: data.pages,
        nextPage: data.pages.length+1,
        pageParam: data.pageParams,
      }),
      getNextPageParam: (lastPage, allPages) => {
        const nextPage = allPages.length;
        return lastPage.nextPage === 0 ? undefined : nextPage;},
    });

  async function getProduct(page) {
    const res = await axios.get(`http://localhost:8081/product/main?page=${page}`);
    const result = res.data;
    console.log(result)
    return {
      result: result.content,
      isLast: res.data.last
    };
  
  }
  useEffect(() => {
    if (inView && hasNextPage) {
      fetchNextPage({
        page: data.nextPage,
      });
    }
  }, [inView, hasNextPage]);
return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "16px" }}>
      {data ? (
        data.pages.map((item) =>
          item.result.map((list, idx) =>
              <Card  lastItemRef={idx === item.result.length - 1 ? ref : null} index={idx} data={list} />
            )
          )
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );

useInView 훅을 사용하여 뷰포트 내에서 요소가 보이면 fetchNextPage 함수를 호출하여 다음 페이지를 가져오도록 했다.

 

무한스크롤을 구현한 화면이다.

 

 

 

inViewtrue이고 hasNextPagetrue일 때 데이터를 가져오는 요청을 보낸다.

더이상 가져올 데이터가 없으면 isLast가 True이기 때문에 다음페이지를 호출하지 않는다.

 


 

구현코드

https://github.com/ungyuun/Clozet/blob/master/src/main/client/src/pages/product/main/Main.jsx

 

참고사이트

https://s0ojin.tistory.com/58

 

[React] react-query useInfiniteQuery로 무한스크롤 구현하기

무한스크롤(Infinite Scroll)? 게시판 글 리스트처럼 많은 데이터를 배열로 받아오는 경우, 그 데이터가 너무 방대해지면 api 요청으로 데이터를 받아오는 시간이 오래걸릴 수 밖에 없게됩니다. 우리

s0ojin.tistory.com