1.페이징 버튼 생성 및 렌더링
페이징 버튼을 만들어 사용자가 페이지 간에 이동할 수 있게 합니다. 여기서는 Pagination 컴포넌트를 사용하여 페이지 버튼을 렌더링합니다.
다음 Pagination 컴포넌트 소스를 가져다 사용하면 된다.
그리고 현재 페이지, 한페지에 표시할 목록수 , 전체 갯수
Pagination.tsx
import Link from "next/link"; import React from "react"; interface PaginationProps { page: number; pageSize: number; totalItems: number; } const Pagination: React.FC<PaginationProps> = ({ page, pageSize, totalItems, }) => { const totalPages = Math.ceil(totalItems / pageSize); // 페이지 버튼의 범위를 계산합니다 const numButtons = 5; // 보여줄 페이지 버튼의 개수 const startPage = Math.max(1, page - Math.floor(numButtons / 2)); const endPage = Math.min(totalPages, startPage + numButtons - 1); return ( <section className="container mx-auto flex justify-center items-center my-8"> {page > 1 ? ( <Link href={`/properties?page=${page - 1}`} className="mr-2 px-2 py-1 border border-gray-300 rounded"> 이전 </Link> ) : null} {/* 페이지 번호 버튼을 렌더링합니다 */} {Array.from({ length: endPage - startPage + 1 }, (_, index) => startPage + index).map((pageNumber) => ( <Link key={pageNumber} href={`/properties?page=${pageNumber}`} className={`mx-1 px-2 py-1 border border-gray-300 rounded ${pageNumber === page ? 'bg-gray-300' : ''}`} > {pageNumber} </Link> ))} {page < totalPages ? ( <Link href={`/properties?page=${page + 1}`} className="ml-2 px-2 py-1 border border-gray-300 rounded"> 다음 </Link> ) : null} </section> ); }; export default Pagination;
넥스트의 searchParams 를 이용해서 파라미터 page, pageSize 를 url 받는다.
없을 경우 기본값은 {page=1, pageSize=3} 로 처리 한다.
받아온 파라미터 값을 서버에서 데이터 처리해서 받아오면 된다.
예) PropertiesPage
import { NextPage } from "next"; import PropertyCard from "@/components/properties/PropertyCard"; import { Suspense } from "react"; import LoadingPage from "../loading"; import { propertyList } from "@/actions/mongodb/properties/property/propertyList"; import Pagination from "@/components/common/Pagination"; export interface PropertiesPageProps{ searchParams: {page: number, pageSize: number} } const PropertiesPage: NextPage<PropertiesPageProps> =async ({searchParams: {page=1, pageSize=3}} ) => { const {total , properties}= await propertyList({page, pageSize}); const showPagination = total && total > pageSize; return ( <section className="px-4 py-6"> <div className="container-xl lg:container m-auto px-4 py-6"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 text-center"> <Suspense fallback={<LoadingPage loading={true} />}> {properties && Array.isArray(properties) && properties.map((property: any) => ( <PropertyCard key={property._id} property={property} /> ))} </Suspense> </div> {!properties || properties.length===0 ? (<p className="grid grid-cols-1 md:grid-cols-1 gap-3 text-center">등록된 게시글이 없습니다.</p>) : null} {showPagination && <Pagination page={Number(page)} pageSize={Number(pageSize)} totalItems={Number(total)} /> } </div> </section> ); }; export default PropertiesPage;
리액트
Pagination.tsx
import React from "react"; interface PaginationProps { currentPage: number; pageSize: number; totalItems: number; onPageChange: (currentPage: number) => void; } const Pagination: React.FC<PaginationProps> = ({ currentPage, pageSize, totalItems, onPageChange }) => { const totalPages = Math.ceil(totalItems / pageSize); const handlePageClick = (newPage: number) => { onPageChange(newPage); // 부모에서 상태 관리 }; return ( <section className="container mx-auto flex justify-center items-center my-8"> {currentPage > 1 && ( <button onClick={() => handlePageClick(currentPage - 1)} className="mr-2 px-2 py-1 border border-gray-300 rounded"> 이전 </button> )} {Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => ( <button key={p} onClick={() => handlePageClick(p)} className={`mx-1 px-2 py-1 border rounded ${p === currentPage ? 'bg-blue-600 border-blue-600 text-white' : ' border-gray-300'}`} > {p} </button> ))} {currentPage < totalPages && ( <button onClick={() => handlePageClick(currentPage + 1)} className="ml-2 px-2 py-1 border border-gray-300 rounded"> 다음 </button> )} </section> ); }; export default Pagination;
TodoListPage 에서 Pagination.tsx사용예 :
import TodoSearchComponent from '@/components/todo/TodoSearchComponent' import TodosListComponent from '@/components/todo/TodosListComponent' import React, { useState } from 'react' import { Link } from 'react-router-dom' import { useQuery } from '@tanstack/react-query'; import { TodoDTOListRes } from '@/dto/TodoDTO'; import { fetchTodos } from '@/actions/todoAction'; import { queryClient } from '@/utils/queryClient'; import Pagination from '@/components/common/Pagination'; const TodoListPage: React.FC = () => { const [orderBy, setOrderBy] = useState('id'); const [done, setDone] = useState('all'); const [searchType, setSearchType] = useState(''); const [searchKeyword, setSearchKeyword] = useState(''); const [currentPage, setCurrentPage] = useState(1); const { data: todos, isLoading, isError, error } = useQuery<TodoDTOListRes, Error>({ queryKey: ['todos', {currentPage, searchType, searchKeyword,orderBy, done }], queryFn: () => fetchTodos(currentPage, searchType, searchKeyword, orderBy, done), }); const todoSearch = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); setCurrentPage(1); // 검색 시 페이지 초기화 queryClient.invalidateQueries({ queryKey: ['todos', {currentPage: 1 , searchType, searchKeyword,orderBy, done}] }); }; const orderByChange = (event: React.ChangeEvent<HTMLSelectElement>) => { setOrderBy(event.target.value); queryClient.invalidateQueries({ queryKey: ['todos', {currentPage: 1 , searchType, searchKeyword,orderBy, done}] }); } const paginationAction = (currentPage: number) => { setCurrentPage(currentPage); } return ( <> <div className="w-full flex flex-row items-center justify-between"> <h1 className="text-3xl font-bold flex-grow text-center mt-10 mb-10">Todo List!</h1> <Link to={`/todo/create`} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Todo 생성 </Link> </div> <TodoSearchComponent orderByChange={orderByChange} setDone={setDone} todoSearch={todoSearch} setSearchType={setSearchType} setSearchKeyword={setSearchKeyword} /> <TodosListComponent todos={todos?.todos} isLoading={isLoading} isError={isError} error={error} /> <Pagination currentPage={currentPage} pageSize={todos?.pageMaker?.pageSize|| 10} totalItems={todos?.pageMaker?.totalCount || 0} onPageChange={paginationAction} // 페이지 변경 핸들러 /> </> ); }; export default TodoListPage;
댓글 ( 0)
댓글 남기기