[react] react-intersection-observer를 사용하여 pagination 구현하기

potato·2024년 6월 19일

react

목록 보기
2/7
post-thumbnail

대량의 데이터를 한번에 렌더링 하게 되면 사이트 사용중 느려짐이 발생할 수 있습니다. 그렇게 되면 사용자가 불편함을 느낄 수 있는데, 이를 방지하기 위해 데이터를 일정 개수 만큼씩만 가져오는 pagination을 구현해보려고 합니다.
다음은 무한 스크롤 형식으로 pagination을 구현하는 방법입니다.

react-intersection-observer

pagination을 쉽게 구현하기 위해 react 라이브러리 react-intersection-observer를 사용하였습니다.

설치

npm install react-intersection-observer --save

사용

먼저, pagination으로 axios 요청하는 코드입니다.

// api.jsx
import axios from 'axios'

const axiosInstance = axios.create({
    baseURL: BASEAPI,
});

function getNews(newsNum, pageNum, success, fail) {
  // newsNum : 한번 부를 때 불러올 뉴스 데이터의 개수
  // pageNum : 뉴스 데이터를 일정 개수로 자른 페이지 수
  const newsUrl = (newsNum, pageNum) => `/articles/news?size=${newsNum}&page=${pageNum}

  return axiosInstance.get(newsUrl)
    .then(success)
    .catch(fail)
}

export { getNews };

다음으로, 페이지네이션으로 데이터를 불러와 렌더링 하는 코드입니다.
useInView 훅을 사용해 구현합니다.

[ref, inView] = useInView()

import { useInView } from 'react-intersection-observer'
import { getNews } from '../api'

import { useRecoilState } from 'recoil'
import { newsDataState } from '../state/atoms'

export default function NewsDetail() {

    // 렌더링 할 데이터
    const [newsData, setNewsData] = useRecoilState(NewsDataState)

    const [page, setPage] = useState(1)
    const [ref, inView] = useInView()

    // 처음 페이지에 진입했을 때 빈 페이지를 방지하기 위해 
    // 0 페이지의 데이터를 렌더링 합니다.
    // 데이터는 10개씩 불러옵니다.

    useEffect(() => {
        getCategoryNews(
            10, 0,
            (response) => {
                setNewsData(response.data)
            },
            ( error ) => {
                console.log(error)
            }
        )
    }, [])


    // 다음 페이지부터는 ref 객체가 보일 때 렌더링 됩니다.
    useEffect(() => {
        if (inView) {
            getCategoryNews(
                10, page,
                ( response ) => {
                    setCategoryData([...newsData, ...response.data])
                    setPage((page) => page + 1)
                },
                ( error ) => {
                    console.log(error)
                }
            )
        }
    }, [inView])


    return (
        <div>
            // 데이터가 있는 경우에만 렌더링
            {newsData.length > 0 ? 
                newsData.map((data) => (
                    <div key={data.article_id}>
                        {data.title} - {data.content}
                    </div>
                )) 
                // 데이터가 없는 경우
                : <div> 결과가 존재하지 않습니다. </div>}
          	<div ref={ref}></div> // 페이지를 내리다 이 객체가 보이면 새로운 데이터 렌더링
        </div>
    )
};

이렇게 하면 스크롤을 내리면서 ref 객체가 보일 때마다 새로운 데이터를 10개씩 불러올 수 있습니다.

profile
초보 프론트엔드 개발자 입니다

0개의 댓글