React/디벨킷 (리액트 프로젝트)

[React] - Intersection Observer로 무한스크롤 (2)

위르겐 2022. 12. 13. 18:36

https://jurgen-94.tistory.com/93

 

[React] - Intersection Observer로 무한스크롤 (1)

프로젝트 내에서 무한스크롤을 구현하기 위해 Intersection Observer API를 사용했으며 그 원론적인 상세내용은 React 무한 스크롤 구현하기 with Intersection Observer 🔥🔥 Intersection Observer API를 이용한 React

jurgen-94.tistory.com

 

1탄에 이어 두번째 글!!

 

 

현 프로젝트에서 

Intersection Observer를 사용하여

무한스크롤을 구현한 곳은 총 세 곳인데

우선은 공지사항을 받아오는 것부터 해보자!

 

( UI적으로 무한스크롤보다는 페이지네이션이 더 나은 것 같은....)

 

Intersection Observer의 동작원리에 대해서는

1탄에서 설명했고

실제로 적용을 해보자!

 

 

function NoticeList({
  notice,
  data,
  error,
  isLoading,
}) {

  const [prevNotices, setPrevNotices] = useState(notice);
  const [getNextNotice] = useGetNextNoticeMutation();

  const onFetchNotices = async () => {
    const last = prevNotices[prevNotices.length - 1];
    const obj = {
      cursorId: last.id,
      id,
    };
    await getNextNotice(obj).then((res) => {
      const nextNotices = res.data.data;
      if (nextNotices.length !== 0) {
        setPrevNotices((prevNotices) => [...prevNotices, ...nextNotices]);
      }
    });
  };

  useEffect(() => {
    setPrevNotices(notice);
  }, [notice]);

  const { target } = useObserver({
    fetcher: onFetchNotices,
    dependency: prevNotices,
    isLoading,
  });

  return (
	...중략...
  );
}

 

(필요한 부분빼고는 전부 지웠습니다)

 

 

 

  const [prevNotices, setPrevNotices] = useState(notice);
  const [getNextNotice] = useGetNextNoticeMutation();

상위컴포넌트에서

notice라는 props를 먼저받아온다.

여기서 notice는 공지사항이 가장 최근 순으로 5개가 담긴 배열이다.

 

 

prevNotices 

즉, 기존 공지사항이라는 state를  선언하고

notice를 state의 초기값으로 선언해준다.

 

이 state를 렌더링해주면

공지사항 5개가 보이게된다.

 

 

 

현 프로젝트에서 RTK Query를 사용해

데이터 페칭 및 캐싱처리를 하고있는데 자세한 설명은 추후 포스팅하겠다.

 

이 RTK Query를 사용해

getNextnotice라는 데이터를 받아오는 함수를 만들어주고

 

 

  const onFetchNotices = async () => {
    const last = prevNotices[prevNotices.length - 1];
    const obj = {
      cursorId: last.id,
      id,
    };
    await getNextNotice(obj).then((res) => {
      const nextNotices = res.data.data;
      if (nextNotices.length !== 0) {
        setPrevNotices((prevNotices) => [...prevNotices, ...nextNotices]);
      }
    });
  };

 

onFetchNotices라는 함수를 선언해

받아온 배열중에서 마지막 공지사항의 id와 

현재 워크스페이스의 id를 객체로 담아

getNextNotices의 파라미터로 담아 보내준 후

데이터를 받아와 

setPrevNotices를 통해

기존 배열에 추가해주면 끝이다.

 

 

( request데이터로 뭘 보내고 response로 뭘 받을지는 

백엔드분과 협의하시길..ㅎㅎ)

 

 

  useEffect(() => {
    setPrevNotices(notice);
  }, [notice]);

 

여기서 주의할점은 아까 위에서

state의 초기값을 props인 notice로 할당해줬었는데

useEffect훅을 통해 

의존성 배열에 notice를 넣고

setPrevNotices(notice)로

notice가 변경될 때마다 이 훅이 실행되게끔 해줘야 정상작동한다.

 

 

 

 

  const { target } = useObserver({
    fetcher: onFetchNotices,
    dependency: prevNotices,
    isLoading,
  });

 

 

직전 글에 올렸던

useObserver라는 커스텀훅에 

각각 

onFetchNotices와 prevNotices 그리고 isLoading을 파라미터로 담아 보내주어

target을 추출해온다.

 

 

이러면 이 target이라는 ref로 설정해둔 

Element가 브라우저에 보일 때

추가 데이터를 받아오는 함수가 작동하게 되는 것이다!

 

 

직전글을 보기 귀찮으신분들을 위해

다시한번 커스텀 훅 코드를 제공하자면

아래와 같다

 

import { useEffect, useRef } from 'react';

export default function useObserver(options) {
  const { fetcher, dependency, isLoading } = options;
  const target = useRef(null);

  useEffect(() => {
    let observer;
    if (target.current && !isLoading) {
      observer = new IntersectionObserver(onIntersect);
      observer.observe(target.current);
    }
    return () => observer && observer.disconnect();
  }, [dependency]);

  const onIntersect = (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        setTimeout(() => {
          fetcher();
        }, 300);
      }
    });
  };

  return { target };
}

 

( 이 훅의 동작원리가 궁금하시다면

꼭 이 글을 읽어보시길 바랍니다 ㅎㅎ )

 

https://jurgen-94.tistory.com/93

 

[React] - Intersection Observer로 무한스크롤 (1)

프로젝트 내에서 무한스크롤을 구현하기 위해 Intersection Observer API를 사용했으며 그 원론적인 상세내용은 React 무한 스크롤 구현하기 with Intersection Observer 🔥🔥 Intersection Observer API를 이용한 React

jurgen-94.tistory.com

 

 

 

이러한 원리로

무한스크롤을 구현했으며

공지사항 외에도

 

주소록
채팅

 

 

이렇게 훅으로 만들어놓으니

다양한곳에서 편하게 쓸 수 있다.

 

 

 

 

끗!

반응형