본문 바로가기
개발/게시판 만들기

[React] 리액트 게시판 만들기 #6 - 페이징과 검색

by onethejay 2023. 5. 8.
728x90

안녕하세요. 원더제이입니다.
이번 포스팅에서는 게시글 목록의 페이징과 검색 기능을 구현해보도록 하겠습니다.

페이징과 검색 기능 추가

이전 포스팅에서 게시글 목록을 가져올때 pagination 정보도 같이 가지고 오게 작업했습니다.

페이징과 검색을 사용할 수 있도록 소스를 수정합니다.

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

const BoardList = () => {
  const navigate = useNavigate();

  const [boardList, setBoardList] = useState([]);
  const [pageList, setPageList] = useState([]);

  const [curPage, setCurPage] = useState(0); //현재 페이지 세팅
  const [prevBlock, setPrevBlock] = useState(0); //이전 페이지 블록
  const [nextBlock, setNextBlock] = useState(0); //다음 페이지 블록
  const [lastPage, setLastPage] = useState(0); //마지막 페이지

  const [search, setSearch] = useState({
    page: 1,
    sk: '',
    sv: '',
  });

  const getBoardList = async () => {
    if (search.page === curPage) return; //현재 페이지와 누른 페이지가 같으면 return

    const queryString = Object.entries(search)
      .map((e) => e.join('='))
      .join('&');

    const resp = await (
      await axios.get('//localhost:8080/board?' + queryString)
    ).data; // 2) 게시글 목록 데이터에 할당

    setBoardList(resp.data); // 3) boardList 변수에 할당
    const pngn = resp.pagination;

    const { endPage, nextBlock, prevBlock, startPage, totalPageCnt } = pngn;

    setCurPage(search.page);
    setPrevBlock(prevBlock);
    setNextBlock(nextBlock);
    setLastPage(totalPageCnt);

    const tmpPages = [];
    for (let i = startPage; i <= endPage; i++) {
      tmpPages.push(i);
    }

    setPageList(tmpPages);
  };

  const moveToWrite = () => {
    navigate('/write');
  };

  const onClick = (event) => {
    let value = event.target.value;
    setSearch({
      ...search,
      page: value,
    });

    getBoardList();
  };

  const onChange = (event) => {
    const { value, name } = event.target; //event.target에서 name과 value만 가져오기
    setSearch({
      ...search,
      [name]: value,
    });
  };

  const onSearch = () => {
    if (search.sk !== '' && search.sv !== '') {
      setSearch({
        ...search,
        page: 1,
      });
      setCurPage(0);
      getBoardList();
    }
  };

  useEffect(() => {
    getBoardList(); // 1) 게시글 목록 조회 함수 호출
  }, [search]);

  return (
    <div>
      <ul>
        {boardList.map((board) => (
          // 4) map 함수로 데이터 출력
          <li key={board.idx}>
            <Link to={`/board/${board.idx}`}>{board.title}</Link>
          </li>
        ))}
      </ul>
      <div>
        <button onClick={onClick} value={1}>
          &lt;&lt;
        </button>
        <button onClick={onClick} value={prevBlock}>
          &lt;
        </button>
        {pageList.map((page, index) => (
          <button key={index} onClick={onClick} value={page}>
            {page}
          </button>
        ))}
        <button onClick={onClick} value={nextBlock}>
          &gt;
        </button>
        <button onClick={onClick} value={lastPage}>
          &gt;&gt;
        </button>
      </div>
      <br />
      <div>
        <select name="sk" onChange={onChange}>
          <option value="">-선택-</option>
          <option value="title">제목</option>
          <option value="contents">내용</option>
        </select>
        <input type="text" name="sv" id="" onChange={onChange} />
        <button onClick={onSearch}>검색</button>
      </div>
      <br />
      <div>
        <button onClick={moveToWrite}>글쓰기</button>
      </div>
    </div>
  );
};

export default BoardList;

페이징과 검색은 개인별로 차이가 있으니 참고해서 수정 작업 해주시면 됩니다.
해당 챕터의 소스는 https://github.com/onethejay/react-board/tree/chap6 에 업로드 되어있으며 챕터 마무리시 master에 마지막 챕터의 소스를 merge 하고 있습니다.
참고가 필요하신분은 해당 깃허브를 참고해주시기 바랍니다 :)

마무리

이번 포스팅까지 해서 Vue 게시판 만들기에 이어서 React 게시판 만들기를 실습했습니다.
React의 기초만 공부해본 상태에서 무엇인가 간단하게 만들어보고 싶어서 작업해봤습니다.
JQuery만 사용했었던 저에게는 새로운 경험이었습니다.

Vue는 html과 script를 따로 작성해야 했지만 React는 JSX를 통해 한번에 작업할 수 있어서 화면 작업 하기에 좀 더 편한 느낌이었습니다.

다만 포스팅을 작성하면서 useState나 useEffect 등에 대한 이해는 부족했기에 공부가 더 필요하다고 생각되었습니다.

다음 프로젝트에서는 React를 적극적으로 도입해서 작업해볼 예정입니다..

지금까지 포스팅을 읽어주셔서 감사합니다.
또 다른 포스팅들로 찾아뵙겠습니다. 😊😊😊

728x90

댓글