도찐개찐
[React] Pagination 페이징 작성 하기 본문
1. Pagination 전용 앱 생성
# 앱설치
$ yarn create react-app pagination
# 설치 된 어플리케이션 경로 이동
$ cd pagination
# 필요 컴포넌트 설치
$ yarn add react-icons prop-types
react-icons :
react에서 자체 배포하고 있는 아이콘 콤포넌트로 버튼 아이콘 사용에 활용하기 위해 설치 합니다.
아이콘 사용이 불필요하신 분들 께서는 설치 하지 않으셔도 됩니다.
prop-types :
props 전달에 자료형을 체크 하기 위해 설치 하였으나 자료형 체크가 불필요하신 분들께서는 설치 하지 않으셔도 됩니다.
2. 작업 파일 및 import 파일 구조
아래 구초 내용을 확인 하셔서 미생성 구조만 생성해 주시면 됩니다.
.
├── App.js # 기본 앱실행 컴포넌트로 Pagination 컴포넌트를 호출
├── css/
| └── Pagination.css
└── components/
└── Pagination.js
3. App.js
* 소스내 주석내용을 확인해 주시면 이해가 편하실 수 있을 거 같습니다.
// App.js
/*
* 필요 컴포넌트 및 css import
*/
import React, { useEffect, useState } from "react";
import Pagination from "./components/Pagination";
import './css/Pagination.css';
/**
* totalPosts - 총 데이터수 ( api 연동 및 데이터 베이스 값 등록 필요 임의 367)
* currentPage - 현재 페이지 위치 - 기본 1페이지
* postsPerPage - 페이지 내 리스팅 갯수 - 기본 10개 리스팅
* pageLimit - 페이징 버튼 출력 갯수 - 기본 5개 리스팅
*/
function App() {
const [totalPosts, setTotalPosts] = useState(367); // 임의 값(데이터 연동 필요)
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage, setPostsPerPage] = useState(10);
const [pageLimit, setPageLimit] = useState(5);
// 자식(Pagination) 컴포넌트에서 자신(App)의 현재 페이지 값을 변경 할 수 있도록 함수화 처리
const updateCurrentPage = (page) => {
setCurrentPage(page);
}
/*
* <Pagination /> 생성시 아래와 같은 props 값 전달
* 설명은 상단 주석 내용 확인
*/
return (
<div className="App">
<Pagination
currentPage={currentPage}
postsPerPage={postsPerPage}
pageLimit={pageLimit}
totalPosts={totalPosts}
paginate={updateCurrentPage}
/>
</div>
);
}
export default App;
4. components/Pagination.js
// components/Pagination.css
/*
* 필요 컴포넌트 임포트
* react-icons 는 별도 아이콘 필요시 사용 불필요한 경우 삭제
*/
import React, { Component } from 'react';
import { MdChevronLeft, MdChevronRight, MdFirstPage, MdLastPage } from "react-icons/md";
import datatype from "prop-types";
/**
* @author Dev-Truly
* @param currentPage 현재 페이지 번호
* @param postsPerPage 페이지 리스팅 수
* @param totalPosts 게시글 총 갯수
* @param pageLimit 페이징 버튼 출력 갯수
* @param paginate 부모 상태 조정 함수
* @returns {JSX.Element}
*/
class Pagination extends Component {
/**
* GetBlockInfo() - 전달 받은 props 데이터 활용하여 페이징 알고리즘 처리 함수
*/
GetBlockInfo = () => {
// 최종 페이지 번호 = 올림(총 데이터 건수 : 367 / 페이지 리스팅 수 : 10 = 36.7 올림 37 페이지)
let lastPage = Math.ceil(this.props.totalPosts / this.props.postsPerPage);
// 현재 페이징 블럭 계산 = 올림(현재 페이지 위치 : 3 / 페이징 버튼 출력수 5 = 0.6 올림 1페이지)
let block = Math.ceil(this.props.currentPage / this.props.pageLimit);
// 블럭내 시작 페이지 계산 = ((현재페이징 블럭 : 1 - 1 = 0) * 페이징 버튼 수 : 5 = 0) + 1 = 1 페이지 시작
let start = ((block - 1) * this.props.pageLimit) + 1;
// 블럭내 종료 페이지 계산 = 낮은 수(마지막 페이지, (시작페이지 + 페이징 버튼수));
let end = Math.min(lastPage, (start + this.props.pageLimit) - 1);
return {lastPage, start, end}
}
/**
* GetPagination() 계산된 페이징 정보 활용하여 components 생성
*/
GetPagination({...blockInfo}) {
//console.log();
// 담을 배열 변수 생성
let components = [];
// 시작 페이지가 1보다 크면 출력
// 1번 페이지 이동 버튼 활성화
// icon MdFirstPage 컴포넌트 확인 불필요시 삭제 후 대체 필요
if (blockInfo.start > 1)
components.push(
<li
className="page-first"
onClick={e=>this.props.paginate(1)}>
<MdFirstPage size={20} />
</li>
);
// 현재 페이지가 1보다 크면 생성
// 직전 페이지 이동 버튼 활성화
// icon MdChevronLeft 컴포넌트 확인 불필요시 삭제 후 대체 필요
if (1 < this.props.currentPage)
components.push(
<li
className="page-previous"
onClick={e=>this.props.paginate(this.props.currentPage - 1)}
>
<MdChevronLeft size={20} />
</li>
);
// 블록 시작 부터 종료 지점까지 반복 실행
// 일반 숫자 버튼 활성화
// currentPage(현재 페이지)와 반복중 증가 연산자의 값이 같으면 클릭 기능 비활성화
// this.props.paginate(i) 부모 컴포넌트에서 전달 받은 setState 함수 처리
for (let i = blockInfo.start; i <= blockInfo.end; i++) {
let currentPageClass = "";
if (this.props.currentPage === i) currentPageClass = "current-page";
components.push(
<li
className={`page-number ${currentPageClass}` }
onClick={
(currentPageClass === "") ?
(e) => this.props.paginate(i) : () => null
}
>
{i}
</li>
);
}
// 현재 페이지가 마지막페이지보다 작으면 생성
// 직후 페이지 이동 버튼 활성화
// icon MdChevronRight 컴포넌트 확인 불필요시 삭제 후 대체 필요
if (this.props.currentPage < blockInfo.lastPage)
components.push(
<li
className="page-next"
onClick={e=>this.props.paginate(this.props.currentPage + 1)
}>
<MdChevronRight size={20} />
</li>
);
// 블록 종료점 페이지가 마지막페이지보다 작으면 생성
// 마지막 페이지 이동 버튼 활성화
// icon MdLastPage 컴포넌트 확인 불필요시 삭제 후 대체 필요
if (blockInfo.end < blockInfo.lastPage)
components.push(
<li
className="page-last"
onClick={e=>this.props.paginate(blockInfo.lastPage)}
>
<MdLastPage size={20} />
</li>
);
// 삽입 된 컴포넌트 리턴
return (
<ul className="page-list-group">
{components}
</ul>
);
}
render() {
let {
currentPage,
postsPerPage,
pageLimit,
totalPosts,
paginate
} = this.props;
// 상기 생성 된 함수 호출
return (
<>
{this.GetPagination(this.GetBlockInfo())}
</>
);
}
}
// 자료형 처리
Pagination.propTypes = {
currentPage: datatype.number,
postsPerPage: datatype.number,
totalPosts: datatype.number,
paginate: datatype.func,
}
export default Pagination;
5. css/Pagination.css
아래 소스를 적용해 주시면 아래 이미지와 같이 현재 페이지(파란색), 마우스오버(빨간색), 기본(검정) 디자인을 사용하실 수 있습니다.
Pagination.js 에서 사용되고 있는 클래스들과 호환 되어 있는 소스로 디자인 변경이 필요하시면 해당 소스에서 수정해 주시면 됩니다.
/* css/Pagination.css */
.page-list-group {
display: inline-block;
}
.page-list-group > li {
list-style: none;
float:left;
padding: 6px 7px;
margin: 5px;
line-height: 19px;
font-size: 15px;
/*border:solid 1px lightgray;*/
border-radius: 5px;
height:20px;
cursor: pointer;
box-shadow: 0px 1px 3px lightgray;
}
.page-list-group > li.page-number {
padding-left: 8px;
padding-right: 8px;
}
.page-list-group > li:hover,
.page-list-group > li.current-page {
padding: 5px 6.5px 5px 6.5px;
font-weight: bold;
border:solid 1px lightgray;
}
.page-list-group > li.current-page {
color: cornflowerblue;
cursor: inherit;
}
.page-list-group > li:hover:not(.current-page) {
color: red;
border:solid 1px lightgray;
}
.page-list-group > li.page-first:hover,
.page-list-group > li.page-previous:hover,
.page-list-group > li.page-next:hover,
.page-list-group > li.page-last:hover {
padding: 5px 6px 5px 6px;
}
공유 소스 경로
https://github.com/dev-truly/react-pagination
728x90
'React' 카테고리의 다른 글
[React] Props 자료형(propType) 선언 하기 (0) | 2022.04.28 |
---|---|
[React] Props VS State (0) | 2022.04.28 |
[React] jQuery 사용하기 (0) | 2022.04.25 |
[MacOS] React 설치 하기 (0) | 2022.04.25 |
React 생명주기 메소드 (0) | 2022.04.21 |
Comments