eunsoolib
React 컴포넌트·훅

pagination

Instance Hook 패턴 기반 React 페이지네이션

데모

INSTANCE HOOK PATTERN

상품 목록

하나의 pagination 인스턴스를 테이블 위·아래 두 컴포넌트가 공유합니다. Provider 없이 props만으로 동기화됩니다.

전체 247개 중 18
ID상품명카테고리가격재고
001상품 001전자기기10,0000
002상품 002의류47,00053
003상품 003식품84,000106
004상품 004도서31,000159
005상품 005전자기기68,00012
006상품 006의류15,00065
007상품 007식품52,000118
008상품 008도서89,000171
// 외부에서 인스턴스 상태에 직접 접근
pagination.page        // 1
pagination.totalPages  // 31
pagination.range       // { start: 1, end: 8 }
pagination.items       // [1, 2, 3, 4, 5, "…", 31]
pagination.isLast      // false

usePagination이 반환하는 하나의 인스턴스를 여러 UI(테이블 위/아래 등)가 props로 공유하면, Provider 없이도 상태가 동기화됩니다. ellipsis(...) 계산 같은 고유 복잡도는 인스턴스 안에 캡슐화됩니다.

설치

pnpm add @cbcruk/pagination

사용법

인스턴스를 공유하는 컴포넌트

import { usePagination, Pagination } from '@cbcruk/pagination'

function ProductTable({ total }: { total: number }) {
  const pagination = usePagination({ total, initialPageSize: 8 })

  const start = (pagination.page - 1) * pagination.pageSize
  const pageData = data.slice(start, start + pagination.pageSize)

  return (
    <>
      {/* 같은 인스턴스를 위·아래에서 공유 → 자동 동기화 */}
      <Pagination pagination={pagination} size="sm" showInfo />
      <Table rows={pageData} />
      <Pagination pagination={pagination} />
    </>
  )
}

인스턴스 없이 컴포넌트만 쓰기

UI가 하나뿐이라 인스턴스를 공유할 필요가 없으면 usePagination 옵션을 Pagination에 바로 넘깁니다.

import { Pagination } from '@cbcruk/pagination'

function Comments({ total, load }: Props) {
  return <Pagination total={total} initialPageSize={8} onChange={load} />
}

인스턴스 직접 제어

pagination.next()
pagination.prev()
pagination.goTo(5) // 범위를 벗어나면 1~totalPages로 clamp
pagination.setPageSize(20) // 첫 페이지로 리셋

pagination.page // 현재 페이지 (항상 1~totalPages)
pagination.totalPages // 전체 페이지 수
pagination.range // { start, end } (1-based)
pagination.items // 렌더링용 번호 배열 (gap은 "...")
pagination.isFirst / pagination.isLast

API

usePagination(options?)

OptionTypeDefaultDescription
totalnumber0전체 항목 수 (보통 서버 응답에서 주입)
initialPagenumber1초기 페이지
initialPageSizenumber10페이지당 항목 수
siblingCountnumber1현재 페이지 양옆 표시 수
boundaryCountnumber1양 끝 표시 수
onChange(page: number) => void-페이지가 실제로 바뀌었을 때 호출
paginationPaginationInstance-기존 인스턴스 재사용

PaginationInstance를 반환합니다.

  • page는 렌더링마다 1~totalPages로 clamp됩니다. 5페이지에서 필터로 결과가 1페이지로 줄면 page1, range·isLast도 그에 맞춰 계산됩니다. 내부에 기억한 페이지는 바꾸지 않으므로, 로딩 중 total이 잠시 0이 됐다가 돌아오면 원래 페이지로 복귀합니다.
  • onChangegoTo·next·prev·setPageSize로 페이지가 실제로 바뀔 때만 호출됩니다. 마지막 페이지에서 next()처럼 제자리면 호출하지 않고, 위의 clamp 보정에도 호출하지 않습니다.

<Pagination />

PropTypeDefaultDescription
paginationPaginationInstance-공유할 인스턴스
showInfobooleanfalse"전체 N개 중 a–b" 표시
size"sm" | "md""md"버튼 크기
classNamestring""래퍼 className

pagination을 넘기지 않으면 usePagination의 나머지 옵션(total, initialPage, initialPageSize, siblingCount, boundaryCount, onChange)을 prop으로 받아 자체 인스턴스를 만듭니다. pagination을 넘기면 이 옵션들은 무시됩니다.

getPaginationRange(params)

페이지 번호 배열(ellipsis 포함)을 계산하는 순수 함수입니다. 커스텀 UI를 직접 만들 때 사용합니다.

getPaginationRange({ page: 5, totalPages: 10 })
// [1, "...", 4, 5, 6, "...", 10]

타입 (자동 생성)

UsePaginationOptions

Prop

Type

On this page