import { useInfiniteQuery } from '@tanstack/react-query'
function Projects() {
const fetchProjects = async ({ pageParam = 0 }) => {
const res = await fetch('/api/projects?cursor=' + pageParam)
return res.json()
}
const {
data,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
status,
} = useInfiniteQuery({
queryKey: ['projects'],
queryFn: 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.data.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>
</>
)
}
=> Number를 return하는 경우 fetchNextPage에 자동으로 pageParam을 전달한다.
data객체는 query data를 포함하는 객체이다.
data 객체에는 pages 라는 배열과 pageParmas라는 fetching시 필요한 파라미터들을 담은 배열이 존재한다.
pageParmas
fetchNextPage, fetchPreviousPage 는 다음페이지, 이전페이지의 데이터를 가져오는데 사용됨.
fetchNextPage를 호출하면, getNextPageParam 옵션을 사용해 다음 페이지의 매개변수를 계산하고, 그 매개변수를 기반으로 새로운 페이지를 서버에서 가져옴
fetchPreviousPage를 호출하면, 페이지의 매개변수를 역방향으로 조정하여 이전 페이지의 매개변수를 계산하고, 그 매개변수를 기반으로 데이터를 가져옴
(수동으로 이전, 다음데이터를 호출하도록 가능)
getNextPageParam이 undefined가 아닌 값을 반환한다면, hasNextPage가 true이다.
getPreviousParam이 undefind가 아닌 값을 반환한다면, hasPreviousPage가 true이다.
웹 페이지에서 DOM 요소의 가시성 및 위치를 감시하고, 요소가 화면에 들어오거나 나갈 때 이벤트를 트리거하는 JavaScript API
Scroll event는 동기적으로 실행되기 때문에 메인스레드에 영향을 줌. 또한 여러 scroll event가 등록되어있을경우 이벤트가 중첩되어 호출되는 현상이 발생가능
Intersection Observer api는 비동기적으로 실행되기 때문에 메인스레드에 영향을 주지 않으면서 변경사항 관찰 가능함.
무한스크롤이나, 페이지 스크롤시 이미지를 Lazy Loading 하는데 사용가능함.
Intersection Observer 객체 생성
IntersectionObserverCallback: IntersectionObserverCallback은 관찰된 요소의 상태가 변경될 때 호출되는 콜백 함수입니다. 이 콜백 함수는 두 개의 매개변수를 받습니다
entries 및 observer.
entries는 IntersectionObserverEntry 객체의 리스트임.
observer는 생성한 인스턴스를 참조함.
const observer = new IntersectionObserver(callback, options);
function callback(entries, observer) {
entries.forEach((entry) => {
// entry.intersectionRatio를 통해 가시성 정보 확인
if (entry.isIntersecting) {
// 요소가 화면에 들어옴
} else {
// 요소가 화면을 벗어남
}
});
}
root : 교차영역의 기준이 될 root 엘리먼트. observe의 대상으로 등록할 엘리먼트는 반드시 root의 하위요소여야만함. (default : null, 브라우저 viewport)
rootMargin : default : '0px 0px 0px 0px' => root element마진값.
threshold : 0 ~ 1 사이의 숫자혹은 이 숫자들의 배열. 타깃 엘리먼트에 대한 교차비율을 의미함. 0이라면, 타깃 엘리먼트가 교차영역에 진입했을때 observer를 실행, 1이라면 타깃 전체가 들어왔을 때 observer를 실행
observe : 타겟에 대한 관찰을 시작할 때 사용함
unobserve : 타깃에 대한 관찰을 멈출 때 사용함.
disconnect : 전체 다수 엘리먼트에 대한 관찰을 멈출때 사용
takeRecords : IntersectionObserverEntry 배열반환.
ref) 공식문서 :https://tanstack.com/query/v4/docs/react/guides/infinite-queries
Intersection Observer api
: https://blog.hyeyoonjung.com/2019/01/09/intersectionobserver-tutorial/
mdn : https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API