[React] 스크롤 페이징 (2) : Intersection Observer

Local Gaji·2023년 8월 9일
0

React

목록 보기
15/18

🎈 Intersection Observer 란?

요소를 관찰해서 요소가 특정 영역 (루트 요소) 안으로 들어오면 특정 동작을 실행하는 API
scroll 이벤트는 스크롤이 움직일때마다 동작해서 성능 부하를 일으키는데, Intersection Observer를 이용하면 이를 개선할 수 있다.


🎈 사용하기


🔰 Intersection Observer 인스턴스 생성

/* 기본 형식 */
const io = new IntersectionObserver(callback, options)

🔰 Options

  • root : 루트 요소를 설정한다. 타겟 요소의 조상 요소여야 한다. 기본값은 브라우저 뷰포트이다.
  • rootMargin : 루트 요소에 margin 값을 설정해서 루트 요소의 범위를 학장한다. css와 같이 4방향의 margin 값을 따로 설정할 수 있다.
  • threshold : 타겟 요소가 몇 퍼센트 이상 보여졌을 때 콜백 함수를 실행할 건지 지정한다. (가시성)

여러 가시성 값을 가질 때마다 콜백함수를 호출하도록 하려면 배열에 값들을 넣어준다.

const io = new IntersectionObserver(callback, {
  threshold: [0, 0.25, 0.5, 0.75, 1]
});

🔰 Callback

콜백함수는 파라미터로 entries 라는 배열 데이터를 받게 된다.
이 배열에는 IntersectionObserverEntry 인스턴스 들이 들어있다.

/* 예시 */
const io = new IntersectionObserver(
  (entries) => {
    entries.forEach(entry => { 
      console.log(entry.isIntersecting)  // 교차 여부 출력
    })
  }, 
);

🔰 관찰 제어

  • io.observe(target) : 타겟 요소 관찰 시작
  • io.unobserve(target) : 타겟 요소 관찰 중지
  • io.disconnect() : 모든 타겟 요소들과의 연결을 해제
  • io.takerecords(target) : Entry 인스턴스들의 배열을 리턴

🎈 무한 스크롤 구현


🔰 useRef 선언

const targetBox = useRef(null);

🔰 타겟 요소를 만들고 ref 걸어주기

<div id="target" ref={targetBox}></div>

요소의 자식 요소가 없다면 css로 높이를 지정해줘야 한다.


🔰 io 타겟 요소로 ref요소 등록하기

io.observe(targetBox.current)

🔰 교차 시 새 페이지 로딩하기

useInfiniteQueryfetchNextPage() 로 새 페이지를 로딩하도록 한다.

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>
)
...

🎈 참고

실무에서 느낀 점을 곁들인 Intersection Observer API 정리

0개의 댓글