Just Do IT!

리액트 custom hook으로 Pagination 구현하기 본문

개발 공부/React

리액트 custom hook으로 Pagination 구현하기

MOON달 2023. 10. 10. 17:47
728x90
Pagination(페이지네이션)이란?

여러개의 컨텐츠를 여러 페이지로 나누고 페이지 번호 버튼, 이전 버튼, 다음 버튼을 눌러서 페이지를 이동하는 기능이다.

  1. 이전 버튼
  2. 페이지 번호 버튼
  3. 다음 버트

총 3가지 버튼을 필수라고 생각하고 기능을 구현했다.

 

 

 

 


이전 글처럼 반복되는 컴포넌트이기도 하고, 이왕 custom hook을 사용하기로 마음 먹은거, 저번 닐리리 프로젝트에서 구현했던 걸 조금 더 보완해보고자 구글링을 해보고 직접 테스트 해보면서 페이지네이션을 구현해봤다.

 

결과는 성공.

아직 기능이 구현된 것이 아니라서 더미 데이터로 페이지네이션을 확인했는데, 생각보다 이런 걸 구현할 수록 더욱 뿌듯해지는 것 같다 ㅋㅋㅋㅋ

 

 

 

 

 

 

usePagination.js 파일 만들기
import { useState } from "react";

function usePagination(data, itemsPerPage) {
  const [currentPage, setCurrentPage] = useState(1);

  // 전체 아이템을 페이지 단위로 나누기
  const indexOfLastItem = currentPage * itemsPerPage;
  const indexOfFirstItem = indexOfLastItem - itemsPerPage;
  const currentItems = data.slice(indexOfFirstItem, indexOfLastItem);

  // 페이지 변경 함수
  const paginate = (pageNumber) => {
    setCurrentPage(pageNumber);
  };

  // 페이지 수 계산
  const totalPages = Math.ceil(data.length / itemsPerPage);

  // 이전 페이지로 이동
  const goToPrevPage = () => {
    if (currentPage > 1) {
      setCurrentPage(currentPage - 1);
    }
  };

  const goToNextPage = () => {
    if (currentPage < totalPages) {
      setCurrentPage(currentPage + 1);
    }
  };

  return {
    currentPage,
    currentItems,
    totalPages,
    paginate,
    goToPrevPage,
    goToNextPage,
  };
}

export default usePagination;

우선 custom hook을 만들기 위해 위의 파일을 만들어서 코드를 구현했다.

 

내가 생각하기에 페이지네이션에서 구현해야 할 기능은 다음과 같았다.

  • 페이지 변경
  • 페이지 수 계산
  • 이전 페이지로 이동
  • 다음 페이지로 이동

 

그래서 custom hook으로 만든 usePagination.js 파일을 보면 위의 기능들이 전부 구현되어 있다.

사실 전체 아이템을 페이지로 만들고, 페이지 수를 계산하고, 이전 버튼/다음 버튼 이렇게 만들면 된다.

페이지네이션 만들 기준은 각 컴포넌트마다 다를 것 같아서 여기에는 적지 않고 해당 컴포넌트에서 적용하기로 생각하고 코드를 만들었다.

 

이전에 닐리리 프로젝트에서 추가할 때는 각 컴포넌트마다 만들고, 중복되는 것 같아서 나중에 custom hook으로 만들었는데, 애초에 중복되는 것들을 계산하고 코드를 구현하는 게 더 효율적이라는 생각이 든다.

 

 

 

 

 

실제로 적용해보기
...

const itemsPerPage = 15; // 페이지 당 보여줄 아이템 수
  const {
    currentPage,
    currentItems,
    totalPages,
    paginate,
    goToPrevPage,
    goToNextPage,
  } = usePagination(
    workData, // 데이터를 workData로 변경
    itemsPerPage
  );
  
 ...
 
 return (
 ...
 		{/* 페이지네이션 컴포넌트 렌더링 */}
        <PaginationContainer>
          <PaginationButton onClick={goToPrevPage}>
            <img src={LeftIcon} alt="left" />
          </PaginationButton>
          {Array.from({ length: totalPages }).map((_, index) => (
            <PageButton
              key={index}
              onClick={() => paginate(index + 1)}
              isSelected={index + 1 === currentPage}
            >
              {index + 1}
            </PageButton>
          ))}
          <PaginationButton onClick={goToNextPage}>
            <img src={RightIcon} alt="right" />
          </PaginationButton>
        </PaginationContainer>
)

...

전체 코드는 생략하고, 페이지네이션 부분 코드만 가져왔다.

 

useState처럼 usePagination을 가져와서 사용한다. 이 컴포넌트에서는 보여줄 아이템 수를 15개로 정했기 때문에 itemsPerPage도 지정해줘야 한다.

 

그리고 페이지네이션 컴포넌트를 렌더링하는 걸로 끝!

icon은 디자이너님이 만들어주신 게 있어서 그걸 import 해서 사용하였고, 나머지는 map으로 구현했다.

기능이 추가가 되지 않아서 추후에 수정될 수도 있지만, 지금은 더미 데이터이므로 이정도로도 페이지네이션이 구현가능했다.

 

아래가 해당 부분을 캡처한 것이다.

이전/다음 버튼을 누르면 이동가능하고, 숫자를 눌러도 이동 가능하다.

페이지네이션이 되는지 안되는지 만들기 위해서 데이터를 많이 만들어서 실제 코드는 길고 지저분하지만....ㅋㅋㅋ

기능 추가하면 더 효율적으로 개선할 방법을 찾아야 겠다.

 

 

 

 

 

 

 

 

 

 


나름 custom hook 시리즈(?)를 만들면서 블로그에 기록했는데, 이전에도 언급했지만 효율적인 코드란 무엇인지 자꾸 고민하게 된다. 물론 지금의 방법도 최적의 방법이 아닌 것 같기는 하지만, 공부하고 있으니까 언젠가는 더 발전하겠지?

 

캠프할 때는 마냥 custom hook 단어 자체가 어렵게 느껴졌는데, 한두번 해보니까 벽 같이 느껴지지는 않는다.

반복되는 컴포넌트를 미리 고민해보고 큰 그림을 그리는 연습을 하는 느낌이다. 아무래도 프로젝트 규모가 전보다 커서 그런것인지. 작은 프로젝트라도 숲을 그리고 나무를 그려야 하는데, 이번에 최대한 그렇게 해보려고 노력 중이다.

 

그래서 이런 것들도 만들어보고...ㅋㅋㅋㅋㅋ 역시 개발을 하는 게 재미있기는 하다.