요소를 관찰해서 요소가 특정 영역 (루트 요소) 안으로 들어오면 특정 동작을 실행하는 API
scroll
이벤트는 스크롤이 움직일때마다 동작해서 성능 부하를 일으키는데, Intersection Observer
를 이용하면 이를 개선할 수 있다.
/* 기본 형식 */
const io = new IntersectionObserver(callback, options)
root
: 루트 요소를 설정한다. 타겟 요소의 조상 요소여야 한다. 기본값은 브라우저 뷰포트이다. rootMargin
: 루트 요소에 margin
값을 설정해서 루트 요소의 범위를 학장한다. css와 같이 4방향의 margin
값을 따로 설정할 수 있다.threshold
: 타겟 요소가 몇 퍼센트 이상 보여졌을 때 콜백 함수를 실행할 건지 지정한다. (가시성) 여러 가시성 값을 가질 때마다 콜백함수를 호출하도록 하려면 배열에 값들을 넣어준다.
const io = new IntersectionObserver(callback, {
threshold: [0, 0.25, 0.5, 0.75, 1]
});
콜백함수는 파라미터로 entries
라는 배열 데이터를 받게 된다.
이 배열에는 IntersectionObserverEntry 인스턴스
들이 들어있다.
/* 예시 */
const io = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
console.log(entry.isIntersecting) // 교차 여부 출력
})
},
);
io.observe(target)
: 타겟 요소 관찰 시작const targetBox = useRef(null);
<div id="target" ref={targetBox}></div>
요소의 자식 요소가 없다면 css로 높이를 지정해줘야 한다.
io.observe(targetBox.current)
useInfiniteQuery
의 fetchNextPage()
로 새 페이지를 로딩하도록 한다.
const io = new IntersectionObserver(
(entries) => {
if (!entries[0].isIntersecting) {return;}
fetchNextPage();
},
{ threshold: 0.1 }
);
useEffect
를 이용해 다음 페이지의 존재여부 (hasNextPage
)에 따라
I.O.
를 생성 > 타겟 등록 > 타겟 해제 해주었다.
...
const targetBox = useRef(null);
useEffect(() => {
const io = new IntersectionObserver(
(entries) => {
if (!entries[0].isIntersecting) {return;}
fetchNextPage();
},
{ threshold: 0.1 }
);
// 다음 페이지가 있으면 타겟 등록, 없으면 등록 해제
if (hasNextPage) {
io.observe(targetBox.current)
}
else if (hasNextPage === false) {
io.disconnect();
}
// 클린업으로 등록 해제를 해줘야함
return () => {io.disconnect();}
}, [hasNextPage])
return (
<목록컴포넌트 />
<div id="target" ref={targetBox}></div>
)
...