55555-Jyeon / Boilerplate

personal boilerplate
0 stars 0 forks source link

[2024.01.10] IntersectionObserver #8

Closed 55555-Jyeon closed 8 months ago

55555-Jyeon commented 10 months ago

🟡 IntersectionObserver 적용하기

현재는 스크롤의 위치로 무한 스크롤을 할 수 있도록 코드가 짜여져 있다. 무한 스크롤을 검색하다보면 IntersectionObserver을 사용하는 것이 훨씬 좋다고 하는데 향후 이거로 변경할 수 있을지..!

우선 hooks 폴더에 만들어두었다.

Screenshot 2024-01-10 at 11 23 51 PM

참고할 자료 👉 MDN 보러가기 참고할 자료 👉 블로그 참고 하러 가기

55555-Jyeon commented 8 months ago

🟢 solved!

처음에 훅함수를 미리 분리하는 등.. 너무 복잡하게 생각해서 잘 안 됐던 것 같다. 2024.02.27 해결 완료

아래와 같이 react-intersection-observer의 useInView를 사용해 전보다 쉽게 무한 스크롤을 구현했다.

참고 사이트 👉 https://www.npmjs.com/package/react-intersection-observer

import { useEffect, useRef } from "react";
import { useInView } from "react-intersection-observer";

const HomePage = () => {
  const containerRef = useRef();
  const { ref, inView } = useInView({
    triggerOnce: true,
  });

  const {
    data: postList,
    fetchNextPage,
    hasNextPage,
  } = useInfiniteQuery({
    queryKey: [POST_QUERY_KEY.POST_LIST],
    queryFn: ({ pageParam = 1 }) => Api.fetchPostList(pageParam),
    getNextPageParam: (lastPage) => {
      const page = lastPage.page;
      if (lastPage.total_pages === page) return true;
      return page + 1;
    },
  });

  useEffect(() => {
    if (inView && hasNextPage) {
      fetchNextPage();
      console.log("fetchNextPage called!");
    }
  }, [inView, hasNextPage, fetchNextPage]);

  return (
    postList && (
      <Container ref={containerRef}>
        <Contents>
          {postList?.pages.map((page) => {
            return page?.map((post) =>
              post.map((el) => <OnePost key={el.id} post={el} user={el.User} />)
            );
          })}
        </Contents>
        <div ref={ref} />
      </Container>
    )
  );
};

export default HomePage;
55555-Jyeon commented 8 months ago

| detail desc.

1️⃣ const containerRef = useRef(); → useRef로 스크롤 감지하기 위한 container 생성

containerRef는 컴포넌트에서 사용할 DOM 요소에 대한 참조를 갖고 있다. 이 경우, IntersectionObserver와 함께 스크롤 감지를 위한 컨테이너 역할을 한다.


2️⃣ const { ref, inView } = useInView({triggerOnce: true}); → useInView 훅(hook)을 이용한 ref 및 inView 생성

useInView 훅은 요소가 화면에 나타날 때를 감지하기 위한 함수다. triggerOnce: true 옵션은 한 번만 감지하도록 하는 설정, ref는 해당 요소에 연결될 참조, inView는 해당 요소가 화면에 보이는지 여부를 나타내는 불리언 값.


3️⃣ useInfiniteQuery를 이용한 데이터 불러오기 설정

이 부분은 이전 무한스크롤과 동일


4️⃣ useEffect를 이용한 무한 스크롤 감지 및 데이터 불러오기

useEffect(() => { if (inView && hasNextPage) fetchNextPage()}, [inView, hasNextPage, fetchNextPage]);

useEffect를 사용해 inView가 true이고 hasNextPage가 true인 경우에만 fetchNextPage를 호출하여 다음 페이지의 데이터를 fetch.