클라이언트에서 전체 데이터 한번에 받아서 페이지 누를때마다 다른 데이터 보여주기
postPerPage
) 보여준다//App.js
import { useState, useEffect } from "react";
import axios from "axios";
import Post from "./Post";
import Pagination from "./Pagination";
function App() {
const [posts, setPosts] = useState([]); //받아온 전체 데이터 저장
const [currentPage, setCurrentPage] = useState(1); //현재 페이지는 1로 기본설정
const [postPerPage, setPostPerPage] = useState(10); //한페이지에 10개의 데이터 보여주기
useEffect(() => {
const fetchPosts = async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/posts");
setPosts(res.data); //모든 데이터가 posts에 저장됨
};
fetchPosts();
}, []);
let indexOfLastPost = currentPage * postPerPage; //보여줄 마지막 데이터의 인덱스
let indexOfFirstPost = indexOfLastPost - postPerPage; //보여줄 첫번째 데이터의 인덱스
let currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost); //indexOfFirstPost번째부터 indexOfLastPost-1까지
const paginate = (pageNum) => setCurrentPage(pageNum); //현재 페이지를 변경하는 함수
return (
<div>
<h2>My Blog Title</h2>
<Post posts={currentPosts} />
<Pagination
postPerPage={postPerPage}
totalPosts={posts.length}
paginate={paginate}
/>
</div>
);
}
export default App;
//Post.js
const Post = ({ posts }) => {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
};
export default Post;
//Pagination.js
const Pagination = ({ postPerPage, totalPosts, paginate }) => {
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(totalPosts / postPerPage); i++) {
pageNumbers.push(i);
}
return (
<nav>
<ul>
{pageNumbers.map((num) => (
<li key={num}>
<a onClick={() => paginate(num)} href="!#">
{num}
</a>
</li>
))}
</ul>
</nav>
);
};
export default Pagination;
클라이언트에서 page를 query로 보내면 서버에서 그에 맞는 데이터 보내주기
<
,>
버튼클릭시 이전, 다음 페이지로 이동<<
,>>
버튼 클릭시 처음, 마지막 페이지로 이동//Pagination.js 페이지네이션 컴포넌트
import './Pagination.css';
const Pagination = ({
activePage,
itemsCountPerPage,
totalItemsCount,
pageRangeDisplayed,
paginate
}) => {
const pageNumbers = [];
const toalPages = Math.ceil(totalItemsCount/itemsCountPerPage);
const maxPage = pageRangeDisplayed;
let pages = 0;
if(totalPages < maxPage) {
//5페이지까지 최대로 띄울 수 있는데 3페이지까지만 필요한 경우
pages = totalPage;
}else{
pages = maxPage;
}
for(let i=1; i<=pages; i++){
pageNumbers.push(i);
}
return (
<>
<div className='pagination-container'>
<span
className='first'
style={{ color: '#C4C4C4', fontWeight: 'bold'}}
onClick={() => {activePage > pageRangeDisplayed ? paginate(activePage - pageRangeDisplayed : paginate(1)}}
><<
</span>
<span
className='prev'
style={{ color: '#C4C4C4', fontWeight: 'bold' }}
onClick={() => {
activePage > 1 ? paginate(activePage - 1) : paginate(activePage);
}}
><
</span>
<ul className='paging-group'>
{pageNumbers.map((num) => {
return (
<li key={num} className={activePage === num? 'active' : ''}>
<span className='paging-num' onClick={()=> paginate(num)}>
{num}
</span>
</li>
</ul>
<span
className='next'
style={{ color: '#C4C4C4', fontWeight: 'bold' }}
onClick={() => {
activePage < totalPage
? paginate(activePage + 1)
: paginate(activePage);
}}
>>
</span>
<span
className='last'
style={{ color: '#C4C4C4', fontWeight: 'bold' }}
onClick={() => paginate(totalPage)}
>>>
</span>
</div>
</>
)
};
export default Pagination;
//postList.js
/*서버에서는 sequelize를 사용해서 findAndCountAll을 쓸 경우,
offest, limit을 설정해서 전달할 수 있다.
즉, 서버에서는 req.query로 전달받은 page와 설정된 limit에 따라 약속된 만큼의
데이터와 총 데이터 개수를 전달한다.
*/
const { page, nickname } = req.query;
const limit = 7;
const offset = (page - 1) * limit;
//이하 생략
const { count, rows } = await Post.findAndCountAll({
where: {
[Op.or]: [
{ hostId: data1.dataValues.id },
{ guestId: data1.dataValues.id },
],
},
include: [
{ model: User, as: "guests", attributes: ["nickname"] },
{ model: User, as: "hosts", attributes: ["nickname"] },
],
offset,
limit,
order: [["createdAt", "ASC"]],
});