-
Notifications
You must be signed in to change notification settings - Fork 7
Infinite scroll 구현하기
SunHo Park edited this page Sep 13, 2022
·
2 revisions
Intersection Observer API는 타겟 요소와 상위 요소 또는 최상위 document 의 viewport사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법이다.
https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
브라우저의 viewport와 target으로 설정한 요소의 교차점을 관찰하여 그 target이 viewport에 포함되는지 구별하는 기능을 제공한다. 이를 통해 성능적으로 더 나은 무한 스크롤을 구현할 수 있게 된다.
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
observer callback이 호출되는 상황을 조작한다. 기준값, 여백, 가시성(어디까지 보일 때 실행시킬지)를 설정할 수 있다.
target이 만나졌을 때 callback이 실행된다. callback은 IntersectionObserverEntry 목록과 observer를 넘겨받는다.
import { useInfiniteQuery } from '@tanstack/react-query'
function Projects() {
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,
})
return status === 'loading' ? (
<p>Loading...</p>
) : status === 'error' ? (
<p>Error: {error.message}</p>
) : (
<>
{data.pages.map((group, i) => (
<React.Fragment key={i}>
{group.projects.map(project => (
<p key={project.id}>{project.name}</p>
))}
</React.Fragment>
))}
<div>
<button
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetchingNextPage}
>
{isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'}
</button>
</div>
<div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div>
</>
)
}
getNextPageParam에서 첫번째 매개변수는 fetch해온 데이터, 두번째 매개변수는 지금까지 가져왔던 page들을 배열이다. 이때 return해주는 값은 다음 값을 불러올 때 param으로 사용된다. pageParam으로는 숫자, 객체 모든 것이 들어갈 수 있음에 주의하자. {pageParms: { pageNumber: 1, keyword: ‘검색어'}} 형식으로도 사용이 가능하다
intersection이 일어날 때마다 infiniteQuery를 callback으로 넘겨주어 실행시키면 된다.