react-intersection-observer 라이브러리로 무한스크롤 페이지 구현하기

Sungw__k·2022년 7월 26일
0
post-thumbnail

버킷리스트 커뮤니티 사이트 글 목록 페이지를 구현하던 중 무한스크롤 기능을 구현하기로 했고, https://slog.website/post/8 블로그의 글을 참고하여 매우 쉽게 구현했다.

설치

npm install react-intersection-observer


사용

import React from "react"
import { useInView } from "react-intersection-observer"

const App = () => {
  const [ref, inView] = useInView()

  return (
    <div ref={ref}>
      Element {inView.toString()}
    </div>
  )
}

export default App

div에 ref를 걸어주고, 사용자가 div 요소를 보면 inView가 true, 안보면 false로 자동으로 변경된다.
이 방법을 이용하여 무한스크롤 페이지를 구현했다.

import { useInView } from "react-intersection-observer";
//생략

function PostList() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(0);
  const [loading, setLoading] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  const [ref, inView] = useInView();

  const getItems = useCallback(async () => {    //서버에 데이터 페이지별로 요청
    setLoading(true);
    await axios         
      .get(`url/page={page}`)
      .then((res) => {
        ...
      })
      .catch(() => {
      	...
      });
    setLoading(false);
  }, [page]);

  useEffect(() => {  // getItems가 바뀔때 마다 데이터 불러오기
    getItems();
  }, [getItems]);

  useEffect(() => {
    // 사용자가 마지막 요소를 보고 있고, 로딩 중이 아니라면 page+=1
    if (inView && !loading) {
      setIsLoading(true);
      setTimeout(() => {
        setPage((prevState) => prevState + 1);
        setIsLoading(0);
      }, 1500);
    }
  }, [inView]);

  return (
   <div style={{ background: "var(--color-skin)", width: "100%", padding: "50px" }}>
      <div className="postList">
        {items.map((item, i) => {
          if (item) {
            return items.length - 1 == i ? 
              <Post ref={ref} /> : <Post />   // 마지막 요소에 ref 걸기
              
              //생략
              );

getItems 함수는 page가 바뀔 때 마다 재생성 되는 함수이다. 이 함수를 useEffect에 넣게되면 결론적으로 page가 바뀌면 서버에 데이터를 요청하게 된다. 즉 page값만 증가시키게 되면 바로 다음 page에 대한 데이터를 서버에서 가져온다.

두 번째 useEffect는 inView가 true, 즉 사용자가 마지막 요소를 보고 있고 로딩중(서버에서 데이터를 받는 중)이 아니라면 page를 증가시킨다. isLoading state는 스크롤이 끝에 가게되면 1.5초간 로딩 애니메이션을 보여주기 위해 정의했다.

0개의 댓글