ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 20221207 TIL 트렌디한 페이지네이션 구현하기
    TIL 2022. 12. 7. 22:57

     

    상품 목록과 주문 목록을 보여줄 때 페이지네이션을 해야한다.

    페이지네이션을 처음에는 과거의 게시판들의 페이지네이션처럼 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 페이지가 있고 > 버튼을 누르면 

    11, 12, 13, 14, 15, 16, 17, 18, 19, 20의 페이지가 보여지는 방식으로 진행을 하려고 했다.

    그런데 디자인을 입히기 위해 찾아보다가 요즘 스타일의 페이지네이션을 보게 되었다.

    https://mui.com/material-ui/react-pagination/

    티스토리 블로그도 글 목록 페이지네이션이 위와 같은 방식으로 구현이 되어 있었다.

    그래서 이 방식으로 페이지네이션을 하기로 결정을 하였다.

     

    이 로직을 구현하기 위해 처음에는 매우 단순하지만 방대한 코드로 시도를 해보았다.

    1. 먼저 총 페이지 수가 7페이지 이하라면 다 보여준다.

    2. 만약 총 페이지 수가 8페이지 이상이고, 현 페이지가 1~4면 1, 2, 3, 4, 5, ..., 10을 보여준다.

    3. 만약 총 페이지 수가 8페이지 이상이고, 현 페이지가 끝에서 4번째 사이면 1, ..., 끝-4, 끝-3, 끝-2, 끝-1, 끝 을 보여준다.

    4. 모두 아니라면 1, ..., 현재 - 1, 현재, 현재 + 1, ..., 끝 을 보여준다.

     

    이 모든 것을 풀어 썼더니 아래와 같이 매우 장황한 코드가 도출되었다.

    import { Link, useNavigate } from 'react-router-dom';
    
    export default function Pagination({ url, totalPages, currentPage = 1 }) {
      const navigate = useNavigate();
    
      const handleClickPrevious = () => {
        navigate(`${url}?page=${currentPage - 1}`);
      };
    
      const handleClickNext = () => {
        navigate(`${url}?page=${Number(currentPage) + 1}`);
      };
    
      if (totalPages === 0) {
        return null;
      }
    
      if (totalPages < 8) {
        return (
          <ul>
            <li>
              <button
                type="button"
                title="previous"
                disabled={currentPage < 2}
                onClick={handleClickPrevious}
              >
                previous
              </button>
            </li>
            {
              [...Array(totalPages).keys()]
                .map((i) => (
                  <li key={i}>
                    <Link to={`${url}?page=${i + 1}`}>{i + 1}</Link>
                  </li>
                ))
            }
            <li>
              <button
                type="button"
                title="next"
                disabled={currentPage > totalPages - 1}
                onClick={handleClickNext}
              >
                next
              </button>
            </li>
          </ul>
        );
      }
    
      if (currentPage < 5) {
        return (
          <ul>
            <li>
              <button
                type="button"
                title="previous"
                disabled={currentPage < 2}
                onClick={handleClickPrevious}
              >
                previous
              </button>
            </li>
            <li>
              <Link to={`${url}?page=1`}>1</Link>
            </li>
            <li>
              <Link to={`${url}?page=2`}>2</Link>
            </li>
            <li>
              <Link to={`${url}?page=3`}>3</Link>
            </li>
            <li>
              <Link to={`${url}?page=4`}>4</Link>
            </li>
            <li>
              <Link to={`${url}?page=5`}>5</Link>
            </li>
            <li>
              <p>...</p>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages}`}>{totalPages}</Link>
            </li>
            <li>
              <button
                type="button"
                title="next"
                disabled={currentPage > totalPages - 1}
                onClick={handleClickNext}
              >
                next
              </button>
            </li>
          </ul>
        );
      }
    
      if (currentPage > totalPages - 4) {
        return (
          <ul>
            <li>
              <button
                type="button"
                title="previous"
                disabled={currentPage < 2}
                onClick={handleClickPrevious}
              >
                previous
              </button>
            </li>
            <li>
              <Link to={`${url}?page=1`}>1</Link>
            </li>
            <li>
              <p>...</p>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages - 4}`}>{totalPages - 4}</Link>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages - 3}`}>{totalPages - 3}</Link>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages - 2}`}>{totalPages - 2}</Link>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages - 1}`}>{totalPages - 1}</Link>
            </li>
            <li>
              <Link to={`${url}?page=${totalPages}`}>{totalPages}</Link>
            </li>
            <li>
              <button
                type="button"
                title="next"
                disabled={currentPage > totalPages - 1}
                onClick={handleClickNext}
              >
                next
              </button>
            </li>
          </ul>
        );
      }
    
      return (
        <ul>
          <li>
            <button
              type="button"
              title="previous"
              disabled={currentPage < 2}
              onClick={handleClickPrevious}
            >
              previous
            </button>
          </li>
          <li>
            <Link to={`${url}?page=1`}>1</Link>
          </li>
          <li>
            <p>...</p>
          </li>
          <li>
            <Link to={`${url}?page=${currentPage - 1}`}>{currentPage - 1}</Link>
          </li>
          <li>
            <Link to={`${url}?page=${currentPage}`}>{currentPage}</Link>
          </li>
          <li>
            <Link to={`${url}?page=${Number(currentPage) + 1}`}>{Number(currentPage) + 1}</Link>
          </li>
          <li>
            <p>...</p>
          </li>
          <li>
            <Link to={`${url}?page=${totalPages}`}>{totalPages}</Link>
          </li>
          <li>
            <button
              type="button"
              title="next"
              disabled={currentPage > totalPages - 1}
              onClick={handleClickNext}
            >
              next
            </button>
          </li>
        </ul>
      );
    }

    작고 소중한 페이지네이션이 구현되었다!

    오늘 리팩토링까지 하려고 했지만 생각보다 다른 부분에 CSS를 적용하는데 시간이 오래 걸려서 아쉽게도 리팩토링은 하지 못했다.

    코드가 너무 중복이 많기 때문에 totalPages와 currentPage를 바탕으로 보여줄 값들(페이지 숫자 혹은 ...)로 이뤄진 배열을 만들고,

    그 배열로 페이지네이션 컴포넌트를 만들게끔 리팩토링을 하면 어떨까 하는 생각을 해보았다.

    모레는 리팩토링 및 배포를 해야하기 때문에 내일 디자인 적용을 마무리하고

    내일까지 페이지네이션 컴포넌트 리팩토링 및 디자인 적용까지 꼭 마무리를 하도록 하자!

     

    댓글

Designed by Tistory.