본문으로 바로가기

게시물을 10개씩 가져오고, Infinite Scroll을 적용하기 위하여

 

React-query의 useInfiniteQuery를 사용하기로 하였다.

 

 

useInfiniteQuery

 

useInfiniteQuery라고 해봤자 useQuery에서 Infinite Scroll과 Pagination을 하기 위한 추가 기능들을 몇개 추가한 것이다.

 

 

data.pages는 fetch된 data들의 집합을 나타낸다.

 

fetch가 트리거될때마다 새로 들어오는 데이터들이 있으니, 한번 fetch될때 가져오는 데이터들을 묶어 pages라는 집합을 만드는 것이다.

 

data.pageParams는 page를 fetch할때 사용할 파라미터를 의미한다.

 

fetchNextPage는 다음 페이지를 가져오는 작업을 하는 함수를 의미하고,

 

getNextPageParam은 다음 페이지의 기준이 될 파라미터를 설정하는 것이다.

 

hasNextPage는 getNextPageParam값이 undefined면 false, 아니면 true를 나타낸다.

   const fetchProjects = ({ pageParam = 0 }) =>
     fetch('/api/projects?cursor=' + pageParam)
 
   const {
     data,
     error,
     fetchNextPage,
     hasNextPage,
     isFetching,
     isFetchingNextPage,
     status,
   } = useInfiniteQuery('projects', fetchProjects, {
     getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
   })
   
   
   const skipToCursor50 = () => fetchNextPage({ pageParam: 50 })

   
   
   return
     <button
           onClick={() => fetchNextPage()}
           disabled={!hasNextPage || isFetchingNextPage}
         >

 

전체적인 코드는 이렇게 생겼다.

 

데이터를 fetch할때 자동으로 getNextPageParam을 통해서 다음 기준이 될 파라미터를 정하고,

 

fetchNextPage 함수를 통해서 다음 페이지를 불러온다.

 

fetchNextPage에 pageParam인자를 넣어서 특정 파라미터로 데이터 fetch를 하도록 할수도 있다.

 

 

 

(Previous 관련 함수도  NextPage 함수와 동일하다)

 

https://react-query.tanstack.com/guides/infinite-queries

 

Infinite Queries

Subscribe to our newsletter The latest TanStack news, articles, and resources, sent to your inbox.

react-query.tanstack.com

 

Cursor based Pagination

 

그리고 Express 상에서 nextCursor 값을 줄때, 마지막 번호라면 undefined를 반환해야 하므로,

 

SELECT MIN(id) as min from posts
SELECT id,user_id, preview_text, title, created_at 
FROM posts 
where id < ${cursor} 
order by id DESC LIMIT 3

 

	nextCursor: rows[rows.length - 1].id > min && rows[rows.length - 1].id,

위와같이 id의 최소값을 가져오고, 이후에 현재 받아온 id값과 비교하여 반환하도록 하였다.

 

IntersectionObserver

 

그리고 useIntersectionObserver Hook을 통해 가장 마지막에 오는 아이템에 접근하게 되면 Infinite Scroll을 하도록 트리거 하였다.

 

import { MutableRefObject, useEffect } from 'react';
import { useRef } from 'react';

function useIntersectionObserver(target: MutableRefObject<any>, fn: Function) {
	useEffect(() => {
		function callback(
			entries: IntersectionObserverEntry[],
			observer: IntersectionObserver
		) {
			entries.forEach((entry) => {
				if (entry.isIntersecting) {
					fn();
				}
			});
		}
		let option = {
			threshold: 1,
		};
		let observer = new IntersectionObserver(callback, option);
		if (!target || !target.current) {
			return;
		}
		observer.observe(target && target.current);
		return () => {
			observer.disconnect();
		};
	}, [fn, target]);
}

export default useIntersectionObserver;

 

트리거의 타겟이 될 target과 그떄 실행하고자 하는 fn을 인자로 받으며,

 

callback함수는 observing하고 있는 entry에 교차하고 있다면 fn 함수를 실행하도록 하였다.

 

만약 target이 null이라면 제대로 observe할수 없으므로 return을 하도록 하였다.

'TIL' 카테고리의 다른 글

TIL 2021-11-10 ICMP 1  (0) 2021.11.10
TIL 2021-11-09 Python Pandas, Spam Filtering  (0) 2021.11.09
TIL 2021-11-06 Next.js12  (0) 2021.11.06
TIL 2021-10-20 IP2  (0) 2021.10.20
TIL 2021-10-15 IP  (0) 2021.10.15