배경
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
복사