Infinity Scroll

Created
2023/11/27 01:51
담당자

배경

View-height 를 활용한 무한 스크롤 구현했다. 스크롤 위치가 바닥에 닿는 순간 다음 페이지를 불러오도록 구현한 것.
useEffect(() => { let fetching = false; const onScroll = async (e: any) => { const { scrollHeight, scrollTop, clientHeight } = e?.target.scrollingElement; if (!fetching && scrollHeight - scrollTop <= clientHeight) { fetching = true; console.log(hasNextPage); if (hasNextPage) await fetchNextPage(); fetching = false; } }; document.addEventListener('scroll', onScroll); return () => { document.removeEventListener('scroll', onScroll); }; }, []);
TypeScript
복사

문제점

scrollEvent로 인해, 한꺼번에 많은 요청 fetch 요청이 연속적으로 발생하는 문제와 가끔씩은 view height 를 제대로 인식하지 못해서 next page 가 undefined이 나는 문제

해결방안

react-intersection-observer를 활용한 무한 스크롤 구현했다. 옵저버가 화면에 보여지는 순간 다음페이지를 불러온다.
import { useInView } from 'react-intersection-observer'; // useRef를 통해 참조하는 html 요소를 패칭된 마지막 요소 아래 두고, // inView를 통해 옵저버 역할을 부여한다. // inView가 뷰포트 내에 보여질 때 마다 다음페이지가 있으면 불러오도록 구현 const { ref, inView } = useInView();
TypeScript
복사
useInfiniteQuery와 react-intersection-observer의 ref 사용
⇒ 스크롤을 계산할 필요 없이 간단하게 데이터를 리패치 가능!
+) useInfiniteQuery의 query key를 사용할 때는 페이지 파라미터를 포함한 인자를 사용해야 한다!
제대로 사용 안하면 리패치 안됨
// useNewsQuery.ts export function useNewsQuery(inputKeyword: string, sort: boolean, filterKeywords: string) { return useInfiniteQuery(['newsList', inputKeyword, sort, filterKeywords], ({ pageParam = 0 }) => getNewsList(accessToken, pageParam, inputKeyword, sort, filterKeywords), { getNextPageParam: (prevData: any, allPages) => { const lastPage = prevData.last; const nextPage = allPages.length + 1; return lastPage ? undefined : nextPage; } }); }
JavaScript
복사