Intersection Observer 와 react-intersection-observer로 무한스크롤 구현하기(without React Hook)

seeun·2022년 3월 11일
0
post-thumbnail

1. Intersection Observer API 사용

📌 Intersection Observer(교차 관찰자 API)란?

Intersection Observer(교차 관찰자 API)는 타겟 엘레멘트와 타겟의 부모 혹은 상위 엘레멘트의 뷰포트가 교차되는 부분을 비동기적으로 관찰하는 API이다.

즉, 화면 상에 내가 지정한 타겟 요소가 보이고 있는지를 관찰하는 API

📌 Intersection Observer 장점, 특징

  • debounce, throttle을 사용하지 않아도 된다.
  • reflow를 하지 않는다.(스크롤 이벤트에서는 현재의 높이 값을 알기 위해 offsetTop을 사용하는데 정확한 값을 가져오기 위해 매번 layout을 새로 그리게 된다고 한다.)
  • 호환성이 좋다

📌 적용해보기

  1. 관찰 대상 생성
  <ListContainer>
        {items.map((item: IlistWithMemo, index: number) => (
          <React.Fragment key={index}>
            {items.length - 1 === index ? (
              <div ref={setTarget}>
                <ListCard
                  key={index}
                  data={item}
                  setOpenModal={setOpenModal}
                  setClickedItem={setClickedItem}
                />
              </div>
            ) : (
              <div>
                <ListCard
                  key={index}
                  data={item}
                  setOpenModal={setOpenModal}
                  setClickedItem={setClickedItem}
                />
              </div>
            )}
          </React.Fragment>
        ))}
 </ListContainer>

"items 길이-1" 이 인덱스와 같다면 마지막 아이템이므로 ref={setTarget} 적용해서 관찰대상 생성


2. new IntersectionObserver(callback, options)로 관찰자 객체를 생성 -> 생성한 관찰자는 관찰 대상을 관찰함!
3. 관찰 대상이 지정한 옵션을 만족하는 상태에 놓이게 되면 콜백 함수 실행

  const options = {
    root: null,
    rootMargin: '0px',
    threshold: 1,
  };

  useEffect(() => {
    if (!setTarget.current) return;
    const observer = new IntersectionObserver(callback, options);
    observer.observe(setTarget.current);
    return () => observer.disconnect();
  }, [options, setTarget]);

  const callback = (entry) => {
    if (entry.isIntersecting && !loadFinished) setPage(page + 1);
  };

🌟 콜백함수 실행 뒤에 관찰 대상 지워주기

스크롤을 내리면서 관찰 대상을 만나고 조건을 만족시키면 콜백함수를 실행하고 새로운 데이터를 가져오게 된다.
이때 observer.disconnect();로 관찰 대상을 지워주고 다시 스크롤을 내렸을 때 관찰 대상이 새롭게 만들어지도록 해야함


2. react-intersection-observer 라이브러리 설치

📌설치

npm i react-intersection-observer


📌적용해보기

const [ref, inView] = useInView();
<ListContainer>
        {items.map((item: IlistWithMemo, index: number) => (
          <React.Fragment key={index}>
            {items.length - 1 === index ? (
              <div ref={ref}>
                <ListCard/>
              </div>
            ) : (
              <div>
                <ListCard />
              </div>
            )}
          </React.Fragment>
        ))}
    </ListContainer>

ref 를 div에 걸어주면 해당 요소가 보이면 inView가 true 로, 안 보이면 false로 자동으로 변경된다.

받아온 "items 길이-1" 이 인덱스와 같다면 마지막 아이템이므로 inView를 true로 변경하여 useEffect 실행하여 데이터를 받아올 수 있도록 구현

  useEffect(() => {
    if (inView && !loading && !loadFinished) {
      setPage((prev) => prev + 1);
    }
  }, [inView, loading, loadFinished]);

Reference

https://nohack.tistory.com/124 [lucid_dream]
https://simian114.gitbook.io/blog/undefined/react/intersectionobserverapi
https://slog.website/post/8

profile
🤹‍♂️개발 기록 노트

0개의 댓글