프로그래밍 공부방

[React] 글 목록 출력에 페이징 추가 본문

프론트엔드/React

[React] 글 목록 출력에 페이징 추가

김갱갱 2022. 8. 13. 22:51

오늘은 저번에 이어서 글 목록을 출력하는데 이에 페이징을 추가해보겠습니다.
글 목록 아래에 페이지 수가 나오고 페이지를 누를 때마다 글목록 부분만 변경됩니다!

왼쪽은 1페이지일 때, 오른쪽은 2페이지일 떼

 
클라이언트 코드
 
전체 코드

import React, { useState, useEffect } from 'react';
import { useNavigate, Link, useParams } from "react-router-dom";

import axios from "axios";

function Plant_info_share() {
  const navigate = useNavigate(); // 페이지 이동을 위해 필요
  
  let one_page_contents = 20; // 한 페이지 당 게시글의 개수
  
  const [contents, setContents] = useState([]); // 게시글 목록
  let [total_contents, setTotalcontents] = useState(); // 게시글의 총 개수
  let [total_pages, setTotalpages] = useState(1); // 총 페이지 개수
  let [remain_contents, setRemaincontents] = useState(); // 나머지 게시글 개수
  
  
  /* 게시글의 총 개수 */
  function total_contents_request() {
    axios.get('http://localhost:5000/board/plant_info_share/total_contents') 
      .then(function (response) {
        setTotalcontents(response.data[0].count); // 게시글의 총 개수 설정
   
        setTotalpages(parseInt(total_contents / one_page_contents));// 총 페이지 개수 설정
        setRemaincontents(total_contents % one_page_contents); // 나머지 게시글 개수 설정
       
        if (remain_contents) { // 한 페이지를 다 채우지 못하는 나머지 게시글이 있다면
          setTotalpages(total_pages => total_pages+1) // 총 페이지에 +1
        } 
      })
      .catch(function (error) {
        console.log(error);
      });
  }
  
  /* 페이지 별 해당하는 게시글들 불러오기*/
  function each_page_contents(current_page) {
    axios.get('http://localhost:5000/board/plant_info_share', { 
      params: {
        current_page: current_page, // 현재 페이지
        one_page_contents: one_page_contents // 한 페이지 당 게시글 개수
      }  
    })
    .then(function (response) { // 서버에서 응답이 왔을 때
      console.log(response.data)
      const data = [...response.data]; // 게시글 목록
      setContents(data);
    })
    .catch(function (error) {
      console.log(error);
    });
  }

  /* 페이지 버튼 생성 */
  function page_button_create() { 
    let button_array = [];
    for (let i=1; i<total_pages+1; i++) {
      button_array.push(<input class="page_btn" key={i} type="button" value={i} onClick={ () => {each_page_contents(i)} } />)
    }
    return button_array;
  }
  
  
  useEffect(() => { each_page_contents(1); }, []) // 처음에 무조건 한 번 실행: 첫 페이지
  useEffect(() => { total_contents_request(); }, [total_contents, remain_contents]) // 뒤에 변수들의 값이 변할 때마다 실행
  
  return (
    <div class="total_div">
      <Header title_setting={title_setting} navbar_setting={navbar_setting}/>
      <div class="content_div">    
        <table>
          <thead>
            <tr>
              <th className="num">번호</th>
              <th className="content_title">제목</th>
              <th className="writer">작성자</th>
              <th className="date">날짜</th>
              <th className="click_count">조회수</th>
            </tr>
          </thead>
          <tbody>
            {contents.map((x) => {
              let link = `/plant_info_share/contents/${x.num}`;

              return (
                <tr>
                  <td className="num">{x.num}</td>
                  <td className="content_title"><Link to = {link}>{x.title}</Link></td>
                  <td className="writer" id="writer1">{x.writer}</td>
                  <td className="date">{x.date}</td>
                  <td className="click_count">{x.clickcount}</td>
                </tr>   
              )        
            })}
          </tbody>
        </table>
      </div>

      <div className='page_button_div'>
        {page_button_create() /* 페이지 출력*/ } 
      </div>
     
      <div className="button_div">
        <input onClick={login_confirm} id="write_button" type="button" value="글쓰기" />
      </div>
    </div>
  );
}

export default Plant_info_share;

 
게시글 총 개수 구하기

  function total_contents_request() { // 게시글의 총 개수
    axios.get('http://localhost:5000/board/plant_info_share/total_contents') // 서버로 get 요청
      .then(function (response) { // 서버에서 응답이 왔을 때
        setTotalcontents(response.data[0].count);
   
        setTotalpages(parseInt(total_contents / one_page_contents));// 총 페이지 개수 설정
        setRemaincontents(total_contents % one_page_contents); // 나머지 게시글 개수 설정
       
        if (remain_contents) { // 현재 페이지가 1페이지가 아니고 나머지 페이지가 있다면
          setTotalpages(total_pages => total_pages+1) // 총 페이지에 +1
        } 
      })
      .catch(function (error) {
        console.log(error);
      });
  }

게시글의 총 개수를 구하기 위해서 서버로 요청을 보냅니다.
응답 받은 값을 setTotalcontents(response.data[0].count) 로 total_Contents 변수에 저장합니다.
그리고 게시글 총 개수를 바탕으로 총 페이지 개수와 나머지 게시글의 개수를 구합니다.
총 페이지 개수 구하는 방법 : parseInt(total_contents/one_page_contents) - 정수 처리
나머지 게시글 개수 설정: total_contents % one_page_contents
 
만약에 나머지 게시글이 있다면 이 말은 곧 페이지가 한 페이지가 더 있다는 뜻이기 때문에
이 경우에는 total_pages에 +1을 해줍니다.
 
 
페이지 버튼 생성

  function each_page_contents(current_page) {
    axios.get('http://localhost:5000/board/plant_info_share', { // 서버로 get 요청
      params: {
        current_page: current_page, 
        one_page_contents: one_page_contents
      }  
    })
    .then(function (response) { // 서버에서 응답이 왔을 때
      const data = [...response.data];
      setContents(data);
    })
    .catch(function (error) {
      console.log(error);
    });
  }

  function page_middle_process(current_page) {
    return function() {
      each_page_contents(current_page);
    }
  }

  // 클로저를 이용해서 가장 마지막 값만 출력되는 오류를 해결
  function page_button_create() { // 페이지 버튼 생성
    let button_array = [];
    for (var i=1; i<total_pages+1; i++) {
      button_array.push(<input key={i} type="button" value={i} onClick={page_middle_process(i)} />)
    }
    return button_array;
  }