Pagination.tsx (1715B)
1 import Link from 'next/link' 2 import { useRouter } from 'next/router' 3 import { ReactNode, useMemo } from 'react' 4 import styles from './Pagination.module.css' 5 6 export type PaginationProps = { 7 page: number 8 } & ({ 9 totalCount: number 10 pageSize: number 11 } | { 12 pageCount: number 13 }) 14 15 export function Pagination (props: PaginationProps) { 16 const router = useRouter() 17 18 const [items, pageCount] = useMemo(() => { 19 const pageCount = 'pageCount' in props 20 ? props.pageCount 21 : Math.ceil(props.totalCount / props.pageSize) 22 23 const from = Math.max(1, props.page - 2) 24 const to = Math.min(pageCount, props.page + 2) 25 26 const items: ReactNode[] = [] 27 for (let i = from; i <= to; i++) { 28 if (i === props.page) { 29 items.push( 30 <span key={`page-${i}`} className={styles.item}>{i}</span>, 31 ) 32 continue 33 } 34 35 items.push( 36 <Link 37 key={`page-${i}`} 38 href={{ 39 pathname: router.pathname, 40 query: { 41 ...router.query, 42 page: i, 43 }, 44 }} 45 className={styles.item} 46 >{i}</Link>, 47 ) 48 } 49 50 return [items, pageCount] 51 }, [props, router]) 52 53 return ( 54 <div className={styles.pagination}> 55 <Link 56 href={{ 57 pathname: router.pathname, 58 query: { 59 ...router.query, 60 page: 1, 61 }, 62 }} 63 className={styles.item} 64 >←</Link> 65 66 {items} 67 68 <Link 69 href={{ 70 pathname: router.pathname, 71 query: { 72 ...router.query, 73 page: pageCount, 74 }, 75 }} 76 className={styles.item} 77 >→</Link> 78 </div> 79 ) 80 }