프로그래밍/React

React Pagination 사용하기

나도 오늘부터 개발자?! 2023. 8. 26. 22:34

Version

React 18.2.0 , Typescript 4.9.5 , Sass 7.0.1

 

사용법

import React from 'react';
import { useState } from 'react';

const Pagination = () => {

  // 페이지당 보여줄 게시물 수
  const MaximumContentItems = 10;

  // DB에서 가져오는 게시물 data
  const [posts, setPosts] = useState(DummyRankingData);

  // 페이지 초기설정 
  const [page, setPage] = useState(1);

  // 
  /**
   * 게시물의 위치 구하는 공식 = 현재 페이지 번호 * 페이지당 보여줄 게시물 수
   * 현재 페이지 번호를 기준으로 표시해줘야할 게시물들의 게시물 위치를 알아야합니다.
   * 현재 페이지 번호에서 1을 뺀 후에 페이지 당 표시할 게시물의 수를 곱하면 게시물의 위치를 알수 있습니다.
   */
  const offset = (page - 1) * MaximumContentItems;

  /**
   * 총 페이지 = 반올림(총 게시물 수 / 페이지당 보여줄 게시물 수)
   * 총 게시물 수 23개라고 가정을 하면 
   * 보여줘야 할 페이지는 3개가 되야 함으로 꼭 올림을 해줘야 합니다.
   */
  const TotalPage = Math.ceil(posts.length/MaximumContentItems);

  // 무결성 검사
  const integrityCheck = posts !== undefined && posts.length > 0;

  return (
      <div className={S.pagination_container}>
        <div className={S.pagination_title_wrapper}>
          <span className={S.pagination_title_txt}>순위</span>
          <div >
            {/* 
              버튼형 페이지네이션 
              TotalPage는 숫자이기 때문에 Array를 사용한 뒤 fill 메소드를 사용하여
              length 만큼 배열을 만들어준 뒤 map을 통해 i 버튼개를 생성 해준 뒤 버튼에 
              i + 1을 해주어 1 부터 length 번째까지 버튼을 구성 해줍니다.
            */}
            {Array(TotalPage).fill(0).map((_, i) =>
              <button
              className={S.pagination_button_number}
                key={i + 1}
                onClick={() => setPage(i + 1)}
                aria-current={page === i + 1 ? "page" : undefined}
              >
                {i + 1}
              </button>
            )}
          </div>
          <div className={S.pagination_button_wrapper}>
              {/* 맨 처음으로 이동해주는 버튼 */}
              <button
                  type='submit'
                  onClick={() => setPage(1)} disabled={page === 1 || TotalPage === 0}
              >
                  <img className={S.first_button} src={first_button} alt='first_button'/>
              </button>
              {/* 왼쪽으로 한 칸씩 이동해주는 버튼 */}
              <button
                  type='submit'
                  onClick={() => setPage(page - 1)} disabled={page === 1 || TotalPage === 0}
              >
                  <img className={S.left_button} src={left_button} alt='left_button'/>
              </button>
              <span>{`${page}/${TotalPage}`}</span>
              {/* 오른쪽으로 한 칸씩 이동해주는 버튼 */}
              <button
                  type='submit'
                  onClick={() => setPage(page + 1)} disabled={page >= TotalPage}
              >
                  <img className={S.right_button} src={right_button} alt='right_button'/>
              </button>
              {/* 맨 마지막으로 이동해주는 버튼 */}
              <button
                  type='submit'
                  onClick={() => setPage(TotalPage)} disabled={page >= TotalPage}
              >
                  <img className={S.last_button} src={last_button} alt='last_button'/>
              </button>
          </div>
        </div>
        <div className={S.pagination_content_wrapper}>
          <div className={S.pagination_content_title_wrapper}>
              <span className={S.title_ranking}>순위</span>
              <span className={S.title_ranking_name}>닉네임</span>
              <span className={S.title_exchange_ranking}>구매수량</span>
          </div>

          {/* 
          무결성 검사 후 각 페이지의 인덱스 및 게시물 개수를 구한 뒤 slice를 통해 10개씩 잘라줌 
          */}
          {integrityCheck && posts.slice(offset, offset + MaximumContentItems).map(items => 
            // eslint-disable-next-line no-nested-ternary
            items.rank <= 3 ? 
            !items.public ?
              <div key={items.rank} className={S.exchange_ranking_content_substance_wrapper}>
                  <span style={{ color: '#795BF8'}} className={S.content_ranking}>{items.rank}</span>
                  <span style={{ color: '#795BF8'}} className={S.content_ranking_name}>{ items.nickname[0] + items.nickname.slice(1).replace(/./g, '*')}</span>
                  <span style={{ color: '#795BF8'}} className={S.content_exchange_ranking}>{items.purchaseQuantity}</span>
              </div>
              :
              <div key={items.rank} className={S.exchange_ranking_content_substance_wrapper}>
                  <span style={{ color: '#795BF8'}} className={S.content_ranking}>{items.rank}</span>
                  <span style={{ color: '#795BF8'}} className={S.content_ranking_name}>{items.nickname}</span>
                  <span style={{ color: '#795BF8'}} className={S.content_exchange_ranking}>{items.purchaseQuantity}</span>
              </div>
            :
            !items.public ?
            <div key={items.rank} className={S.exchange_ranking_content_substance_wrapper}>
                <span className={S.content_ranking}>{items.rank}</span>
                <span className={S.content_ranking_name}>{ items.nickname[0] + items.nickname.slice(1).replace(/./g, '*')}</span>
                <span className={S.content_exchange_ranking}>{items.purchaseQuantity}</span>
            </div>
            :
            <div key={items.rank} className={S.exchange_ranking_content_substance_wrapper}>
                <span className={S.content_ranking}>{items.rank}</span>
                <span className={S.content_ranking_name}>{items.nickname}</span>
                <span className={S.content_exchange_ranking}>{items.purchaseQuantity}</span>
            </div>
          )}
        </div>
      </div>
  )
}

export default Pagination

 

 

'프로그래밍 > React' 카테고리의 다른 글

React + Typescript - Chart.js (DoughnutChart)  (0) 2023.08.26
React + Typscript에 AOS 라이브러리 사용법  (0) 2023.07.24
React-csv 패키지 사용법  (0) 2023.05.15
React useState 란?  (0) 2023.05.11
React useEffect 란?  (0) 2023.05.08