8/7TIL

이세영·2024년 8월 7일
0
post-thumbnail

TIL: React Pagination 컴포넌트 사용법

1. 페이지 네이션 컴포넌트

작성한 페이지 네이션 컴포넌트는 다음과 같습니다:

import React from "react";
import PageButton from "../atoms/PageButton";
import PageNumber from "../atoms/PageNumber";

const prevIcon = "/chevron-left.svg";
const nextIcon = "/chevron-right.svg";

interface PaginationProps {
  currentPage: number;
  totalPages: number;
  onPageChange: (page: number) => void;
}

const Pagination = ({
  currentPage,
  totalPages,
  onPageChange,
}: PaginationProps) => {
  const handlePrev = () => {
    if (currentPage > 1) {
      onPageChange(currentPage - 1);
    }
  };

  const handleNext = () => {
    if (currentPage < totalPages) {
      onPageChange(currentPage + 1);
    }
  };

  const renderPageNumbers = () => {
    const pageNumbers = [];
    const maxVisiblePages = 5;
    const halfVisible = Math.floor(maxVisiblePages / 2);

    let startPage = Math.max(1, currentPage - halfVisible);
    let endPage = Math.min(totalPages, currentPage + halfVisible);

    if (endPage - startPage < maxVisiblePages - 1) {
      if (startPage === 1) {
        endPage = Math.min(maxVisiblePages, totalPages);
      } else {
        startPage = Math.max(1, endPage - (maxVisiblePages - 1));
      }
    }

    for (let i = startPage; i <= endPage; i++) {
      pageNumbers.push(
        <PageNumber
          key={i}
          number={i}
          onClick={onPageChange}
          selected={currentPage === i}
        />
      );
    }

    return pageNumbers;
  };

  return (
    <div className="pagination flex justify-center items-center space-x-2">
      <PageButton
        onClick={handlePrev}
        disabled={currentPage === 1}
        icon={prevIcon}
      />
      {renderPageNumbers()}
      <PageButton
        onClick={handleNext}
        disabled={currentPage === totalPages}
        icon={nextIcon}
      />
    </div>
  );
};

export default Pagination;

2. 페이지 네이션 사용법

페이지 네이션을 사용할 부모 컴포넌트를 작성하는 방법은 다음과 같습니다.

import React, { useState, useEffect } from "react";
import Pagination from "@/components/molecules/Pagination"; // Pagination 경로에 맞게 수정
import ContentsCard from "@/components/molecules/ContentsCard"; // 카드 컴포넌트 경로에 맞게 수정

const itemsPerPage = 6; // 페이지당 보여줄 아이템 수

const ExampleComponent = () => {
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(0);
  const [items, setItems] = useState([]); // 전체 아이템을 저장할 상태

  useEffect(() => {
    // 데이터 fetch 예시 (API 호출)
    const fetchItems = async () => {
      const response = await fetch("/api/items"); // API 경로에 맞게 수정
      const data = await response.json();
      setItems(data.items); // API에서 받아온 아이템 목록
      setTotalPages(Math.ceil(data.total / itemsPerPage)); // 전체 페이지 수 계산
    };
    
    fetchItems();
  }, []);

  const handlePageChange = (page) => {
    setCurrentPage(page); // 현재 페이지 상태 업데이트
  };

  // 현재 페이지에 해당하는 아이템 계산
  const currentItems = items.slice(
    (currentPage - 1) * itemsPerPage,
    currentPage * itemsPerPage
  );

  return (
    <div>
      <h1>페이지 네이션 예제</h1>
      <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
        {currentItems.map(item => (
          <ContentsCard
            key={item.id}
            hotTitle={null}
            newTitle="✨ NEW"
            communityTitle={item.title}
            imageSrc={item.img_url}
            subTitle={item.contents}
          />
        ))}
      </div>
      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        onPageChange={handlePageChange}
      />
    </div>
  );
};

export default ExampleComponent;

3. 주요 포인트

  • 상태 관리: currentPage, totalPages, items를 상태로 관리합니다.
  • 데이터 가져오기: useEffect를 사용하여 컴포넌트가 마운트될 때 아이템을 가져옵니다.
  • 페이지 변경 핸들러: handlePageChange 함수를 작성하여 페이지 변경 시 상태를 업데이트합니다.
  • 현재 페이지 아이템 계산: 슬라이스를 사용하여 현재 페이지에 해당하는 아이템만 표시합니다.
  • 페이지 네이션 컴포넌트: Pagination 컴포넌트를 사용하여 페이지 네이션 기능을 제공합니다.

이렇게 작성하면 페이지 네이션 기능이 잘 작동하며, 사용자에게 페이지를 쉽게 탐색할 수 있는 UI를 제공합니다.

profile
블로그 관리 하루에 한번씩 도전!

0개의 댓글