전시,공연 정보를 제공하는 리액트 프로젝트에서 공연,전시의 데이터의 양이 많아 한 페이지에 모든 정보를 나열하다보니 사용자 경험이 저하된다는 생각이 들었습니다. 이를 해결하기 위해 페이지네이션을 도입하여 사용자에게 전시공연 정보를 정해진 개수만큼 보여지도록 했습니다.
npm install react-paginate
설치가 완료되었다면, 이제 'CurrentExhibitions' 컴포넌트에 페이지네이션 기능을 추가해보겠습니다. 먼저, react-paginate를 컴포넌트에서 사용할 수 있도록 import 합니다. 그리고 'Pagination' 컴포넌트를 생성하여 react-paginate를 사용하도록 합니다.
// Pagination.js
import React from "react";
import ReactPaginate from "react-paginate";
import { FiChevronLeft, FiChevronRight } from "react-icons/fi";
const Pagination = ({ pageCount, onPageChange, currentPage }) => {
return (
<ReactPaginate
previousLabel={<FiChevronLeft />}
nextLabel={<FiChevronRight />}
pageCount={pageCount}
onPageChange={onPageChange}
containerClassName={"pagination"}
pageLinkClassName={"pagination__link"}
activeLinkClassName={"pagination__link__active"}
/>
);
};
export default Pagination;
또한, 페이지네이션 컴포넌트의 스타일을 정의하기 위해 CSS를 작성합니다.
.pagination {
margin-top: 2rem;
width: 100%;
display: flex;
justify-content: center;
gap: 1rem;
> * {
cursor: pointer;
}
}
.pagination__link {
transition: all 0.25s;
padding: 0.2rem 0.6rem;
border-radius: 0.3rem;
}
.pagination__link__active {
background-color: #bbb;
color: #fefefe;
}
설치가 완료되었다면, 이제 공연,전시 목록을 보여주는 컴포넌트에 페이지네이션 기능을 추가해보겠습니다.
먼저, 앞서 만든 Pagenation컴포넌트를 사용할 수 있도록 import 합니다.
import Pagination from "../atoms/Pagination";
그리고 컴포넌트의 return 부분에서 페이지네이션 컴포넌트를 렌더링하도록 합니다.
// 생략...
return (
<>
{/* 생략... */}
{/* 페이지네이션 */}
{pageCount > 0 && (
<Pagination
pageCount={Math.max(1, pageCount - 1)}
onPageChange={handlePageChange}
currentPage={currentPage}
/>
)}
</>
);
페이지네이션을 구현하고 보니 페이지를 넘겨도 화면이 클릭한 위치에 있어 사용자 경험을 저하한다는 생각이 들었습니다.
사용자가 페이지를 이동할 때마다 스크롤이 맨 위로 이동하게 되면, 사용자는 새로운 페이지의 내용을 처음부터 볼 수있을 것입니다. 이를 위해 'handlePageChange' 함수 내부에 window.scrollTo()
함수를 사용하여 스크롤 위치를 새로운 페이지의 첫부분이 보이도록 조정하였습니다.
const handlePageChange = ({ selected }) => {
setCurrentPage(selected);
window.scrollTo(0, 320); // 페이지 변경 시 스크롤을 맨 위로 이동
};
기존에는 데이터를 한번에 처리해서 개별 카테고리 탭을 눌러도 전체에 대한 페이지네이션이 남아있는 문제가 있었습니다. 이를 해결하기 위해 각 카테고리 탭에 따라 보여지는 데이터를 필터링하고 정렬하였습니다. 선택된 카테고리에 따라 필터링된 데이터를 'setFilteredData'를 통해 업데이트하였고, 이에 따라 페이지네이션의 전체 페이지 수도 변경되게 하였습니다.
useEffect(() => {
// 카테고리 변경 시 필터링된 데이터 업데이트
const filtered = data
.filter(
(item) =>
(selectedCategory === "전체" || item.category === selectedCategory) &&
formatDate(item.start) <= new Date() &&
formatDate(item.end) >= new Date()
)
.sort((a, b) =>
sortType === "bookmarked"
? b.bookmarked - a.bookmarked
: new Date(b.start) - new Date(a.start)
);
setFilteredData(filtered);
setCurrentPage(0); // 페이지를 처음으로 초기화
}, [data, selectedCategory, sortType]);
[react-paginate 공식문서]
https://www.npmjs.com/package/react-paginate