react hooks에서
pagination을 구현하고,
라이브러리 react-js-pagination을
사용하여 구현해봅니다.
구현 내용:
1. react hooks
2. 최소한의 css만을 사용합니다.
3. axios로 jsonplaceholder에서 더미데이터를 가져옵니다.
구현 화면
폴더 구조
npm, axios 설치
cra로 프로젝트를 생성하고, 서버통신을 위해 axios를 설치합니다.
npm create react-app react-pagination //react-pagination 프로젝트 생성
npm i axios //axios 설치
App.js
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import './App.css';
import Post from './components/Post';
import Pagination from './components/Pagination';
const App = () => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1); //현재 페이지
const [postPerPage] = useState(15); //페이지당 포스트 개수
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
const res = await axios.get('https://jsonplaceholder.typicode.com/posts')
setPosts(res.data);
setLoading(false);
}
fetchPosts();
}, []);
//현재 페이지 가져오기
const indexOfLastPost = currentPage * postPerPage; //1*10 = 10번 포스트
const indexOfFirstPost = indexOfLastPost - postPerPage; //10-10 = 0번 포스트
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost); //0~10번까지 포스트
//클릭 이벤트-페이지 바꾸기
const paginate = pageNum => setCurrentPage(pageNum);
return (
<div className="container">
<h2>My Blog Title</h2>
<Post posts={currentPosts}/>
<Pagination
postPerPage={postPerPage}
totalPosts={posts.length}
paginate={paginate} />
</div>
);
}
export default App;
components > Post.js
axios를 통해 불러온 포스트 자료들을 Post 컴포넌트에 넣습니다.
import React from 'react';
const Post = ({posts, loading}) => {
if(loading) {
return <h2>...loading</h2>;
}
return (
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
);
};
export default Post;
components > Pagination.js
- 페이지 번호를 출력하는 컴포넌트입니다.
- pagination 컴포넌트는 다른 게시판에서도 컴포넌트만 불러와 바로 사용할 수 있게 합니다.
import React from 'react';
const Pagination = ({postPerPage, totalPosts, paginate}) => {
const pageNumbers = [];
for (let i=1; i<=Math.ceil(totalPosts / postPerPage); i ++) {
pageNumbers.push(i);
}
return (
<nav>
<ul className="pagination">
{pageNumbers.map(num =>
<li key={num}>
<a onClick={() => paginate(num)} href='!#'>{num}</a>
</li>)}
</ul>
</nav>
);
};
export default Pagination;
App.css
.container {
text-align: center;
max-width: 700px;
margin: 0 auto;
}
.container li {
list-style: none;
border: 1px solid #828282;
}
.pagination li {
display: inline-block;
background: #dedede;
overflow: hidden;
}
.pagination li a {
text-decoration: none;
width: 10px;
height: 10px;
padding: 10px;
}
.pagination li a:focus{
background-color: yellow;
}
react-js-pagination 라이브러리
- 페이지네이션 라이브러리를 이용하면 components > Pagination.js 없이 좀더 간편합니다.
- 참고로 redux, redux-toolkit, context api 를 이용한다면 page와 handlePageChange는 중앙에서 따로 관리할 수 있습니다.
부모 컴포넌트
import React, { useState, useEffect } from 'react';
const Box = () => {
const [posts, setPosts] = useState([]) //axios로 받아온 데이터 저장
const [currentPosts, setCurrentPosts] = useState([]) //보여줄 포스트
const [page, setPage] = useState(1) //현재 페이지
const handlePageChange = (page) => { setPage(page) }
const [postPerPage] = useState(7); //페이지당 포스트 개수
const indexOfLastPost = page * postPerPage
const indexOfFirstPost = indexOfLastPost - postPerPage
useEffect(() => {
setPosts([...Lists].reverse()) //Lists는 axios로 받아온 상태에서 거꾸로 정렬
setCurrentPosts(posts.slice(indexOfFirstPost, indexOfLastPost))
}, [indexOfFirstPost, indexOfLastPost, weightLists, page])
return (
<>
<table>
<tbody>
{currentPosts.map((list, idx) =>
<tr key={idx} className='px-6 py-3'>
<td>{...}</td>
</tr>)}
</tbody>
</table>
<Paging totalCount={posts.length} page={page} postPerPage={postPerPage} pageRangeDisplayed={5}
handlePageChange={handlePageChange} page={page} />
</>
);
};
export default Box;
자식 페이지 컴포넌트
import React from "react";
import Pagination from "react-js-pagination";
const Paging = ({ totalCount, postPerPage, pageRangeDisplayed, handlePageChange, page }) => {
return (
<Pagination
activePage={page}
itemsCountPerPage={postPerPage}
totalItemsCount={totalCount ? totalCount : 0}
pageRangeDisplayed={pageRangeDisplayed}
prevPageText={"‹"}
nextPageText={"›"}
onChange={handlePageChange} />);
};
export default Paging;
반응형
'개발 > React' 카테고리의 다른 글
[react] pie 차트 (ft. 도넛 차트 라이브러리) (3) | 2021.09.05 |
---|---|
[react] react-datepicker 커스텀 (0) | 2021.09.02 |
[react] Redux 예제 (ft. 미들웨어, Redux-thunk, Redux-devtools) (0) | 2021.07.18 |
[react] Refusing to install package with name "react-redux" under a package 오류 해결 (0) | 2021.07.11 |
[react] POST url/[object%20Object] 404 (Not Found) 오류 해결 (2) | 2021.07.09 |
댓글