[React] 익명게시판에 pagination 구현하기

김유진·2022년 7월 7일
0

React

목록 보기
13/64
post-custom-banner

1. Pagination이란?

리스트를 보여주는 화면에서, arrow를 앞 뒤로 왔다갔다하면 여러 개의 페이지가 보여지는 것을 말한다. 이를 한번 구현해보자.

2. 익명게시판 Pagination 구현하기

일단 useState를 하나 만들어야 하는데 다음과 같이 만들어 보자. ShowPostList.jsx에 다음 코드를 입력한다.

...
const ShowPostList = ({apiUrl}) => {
    const [loading, setLoading] = useState(true);
    const [isPost, setIsPost] = useState(false);
    const [postList, setPostList] = useState([]);
    const [page, setPage] = useState
...

pagination을 랜더링하기 위하여, map을 통하여 이용할 것이다. 전체 페이지의 개수가 몇개인지 확인을 해 보자.

우리가 받아온 데이터의 count를 확인해보면

92임을 알 수 있다. 전체 글의 개수가 총 92개인데, 우리가 10개만 보여주는 것만이 10개이기 때문에 이정도밖에 안보이는 것이다.

우리는 이 페이지를 나누기 위하여 페이지 데이터를 가져와, 계산을 해야 한다. 92라는 수를 올림을 하여 10으로 나누어 보자. (10페이지가 보여야 하기 때문)

useEffect(() => {
        axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
            console.log(response.data);
            Math.ceil(response.data.count / 10);
            setPostList(response.data.results);
            setLoading(false);
        })
    },[]); 

여기서의 Math.ceil(response.data.count / 10);가 전체 페이지의 개수를 담고 있는 공식이 될 것이다.

전체 페이지를 담고 있는 state가 필요해보이니 추가해보자.

const [pages, setPages] = useState([]);

저기 [] 빈칸에 페이지의 수가 다음과 같이 입력되겠지?
[1,2,3,4,..] 원래는 이렇게 되어야 한다. 이 값을 업데이트 시키기 위해 변수를 하나 만들고 다음과 같이 설정해보자.

 useEffect(() => {
        axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
            console.log(response.data);
            const lastPage = Math.ceil(response.data.count / 10);
            const tempPages = [];
            for(let i = 1 ; i <= lastPage ; i++){
                tempPages.push(i);
            }
            setPages(tempPages);
            setPostList(response.data.results);
            setLoading(false);
        })
    },[]); 

위의 for문을 돌리면서 우리가 가져야 하는 최대 페이지를 계산하고, 그 페이지의 값을 state 업데이트 시키는 방향으로 설정을 완료하였다.

자. 이제 우리가 만든 pages라는 state를 진짜로 번호 넣는것에 map 형식으로 만들어 넣으면 되겠죠!

</PagenumberDiv>
     {pages.map(pageNum => (
         <PagenumberDiv key = {pageNum} > {pageNum} </PagenumberDiv>
     ))}
<PagenumberDiv>

짜잔~ map을 활용하여 진짜 수를 넣어요.

일단 번호가 뜨는 것은 성공했다!
이제, 해당 페이지 번호를 누르면, 진짜로 그 페이지에 맞는 데이터가 바뀌어 등장하는 방법에 대해서 알아보도록 하자.

   useEffect(() => {
        axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
            console.log(response.data);
            const lastPage = Math.ceil(response.data.count / 10);
            const tempPages = [];
            for(let i = 1 ; i <= lastPage ; i++){
                tempPages.push(i);
            }
            setPages(tempPages);
            setPostList(response.data.results);
            setLoading(false);
        })
    },[]); 

위 코드의 useEffect를 현재 처음 페이지를 불러올 때만 한번 랜더링 되는 것이 아니라, 페이지가 바뀔 때마다 새롭게 시작할 수 있도록 바꾸어 주어야 하는 것이다.

    useEffect(() => {
        axios.get(`${apiUrl}list/?page=${page}&page_size=10`).then(response => {
            console.log(response.data);
            const lastPage = Math.ceil(response.data.count / 10);
            const tempPages = [];
            for(let i = 1 ; i <= lastPage ; i++){
                tempPages.push(i);
            }
            setPages(tempPages);
            setPostList(response.data.results);
            setLoading(false);
        })
    },[page]); 

그래서 이렇게, page가 업데이트 될 때마다 useEffect가 실행할 수 있도록 바꾸어 주었다.
그리고

{pages.map(pageNum => (
      <PagenumberDiv key = {pageNum} onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>))}

해당 페이지를 클릭할 때마다 페이지를 바꾸는 기능을 넣어준다. 그럼 페이지를 클릭할 때마다 다른 내용이 뜨는 것을 확인할 수 있다.

자, 이제 앞으로 가기, 뒤로 가기 버튼을 구현해보자. <-, ->가 기능도 없이 있으면 안되니까!

 <PagingSection>
      <PagenumberDiv onClick = {() => setPage(page-1)}>
           <FontAwesomeIcon icon = {faArrowLeft}/>
      </PagenumberDiv>
      {pages.map(pageNum => (
      <PagenumberDiv key = {pageNum} 
             onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>
      ))}
      <PagenumberDiv onClick = {() => setPage(page+1)}>
       <FontAwesomeIcon icon ={faArrowRight}/>
       </PagenumberDiv>
</PagingSection>

+1, -1을 통하여 작동하도록 해 주었다.
그런데 마지막 페이지와 첫 페이지도 +1, -1 페이지가 될 수 있으니까 이를 방지하여 보자.

<PagenumberDiv onClick = {() => {
     if (page > 1) {() => setPage(page-1)}}}>
     <FontAwesomeIcon icon = {faArrowLeft}/></PagenumberDiv>
     {pages.map(pageNum => (
          <PagenumberDiv key = {pageNum} onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>))}
          <PagenumberDiv onClick = {() => {
              if(pages.length > page) {setPage(page+1)}}}>
          <FontAwesomeIcon icon ={faArrowRight}/></PagenumberDiv>

이렇게 코드를 작성하여 작을때만, 클때만 페이지가 넘어가도록 한다.
하지만 UX관점에서 보면 1페이지와 마지막 페이지에, 화살표가 사라지는 것도 좋을 것 같다 :)

post-custom-banner

0개의 댓글