본문 바로가기
개발/React

[react] pagination 구현 (ft. react-js-pagination)

by 코딩하는 갓디노 2021. 7. 25.

react pagination

 

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;
반응형

댓글