hook.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import React, { useCallback } from 'react'
  2. import type { IPaginationProps, IUsePagination } from './type'
  3. const usePagination = ({
  4. currentPage,
  5. setCurrentPage,
  6. truncableText = '...',
  7. truncableClassName = '',
  8. totalPages,
  9. edgePageCount,
  10. middlePagesSiblingCount,
  11. }: IPaginationProps): IUsePagination => {
  12. const pages = Array(totalPages)
  13. .fill(0)
  14. .map((_, i) => i + 1)
  15. const hasPreviousPage = currentPage > 1
  16. const hasNextPage = currentPage < totalPages
  17. const isReachedToFirst = currentPage <= middlePagesSiblingCount
  18. const isReachedToLast = currentPage + middlePagesSiblingCount >= totalPages
  19. const middlePages = React.useMemo(() => {
  20. const middlePageCount = middlePagesSiblingCount * 2 + 1
  21. if (isReachedToFirst)
  22. return pages.slice(0, middlePageCount)
  23. if (isReachedToLast)
  24. return pages.slice(-middlePageCount)
  25. return pages.slice(
  26. currentPage - middlePagesSiblingCount,
  27. currentPage + middlePagesSiblingCount + 1,
  28. )
  29. }, [currentPage, isReachedToFirst, isReachedToLast, middlePagesSiblingCount, pages])
  30. const getAllPreviousPages = useCallback(() => {
  31. return pages.slice(0, middlePages[0] - 1)
  32. }, [middlePages, pages])
  33. const previousPages = React.useMemo(() => {
  34. if (isReachedToFirst || getAllPreviousPages().length < 1)
  35. return []
  36. return pages
  37. .slice(0, edgePageCount)
  38. .filter(p => !middlePages.includes(p))
  39. }, [edgePageCount, getAllPreviousPages, isReachedToFirst, middlePages, pages])
  40. const getAllNextPages = React.useMemo(() => {
  41. return pages.slice(
  42. middlePages[middlePages.length - 1],
  43. pages[pages.length],
  44. )
  45. }, [pages, middlePages])
  46. const nextPages = React.useMemo(() => {
  47. if (isReachedToLast)
  48. return []
  49. if (getAllNextPages.length < 1)
  50. return []
  51. return pages
  52. .slice(pages.length - edgePageCount, pages.length)
  53. .filter(p => !middlePages.includes(p))
  54. }, [edgePageCount, getAllNextPages.length, isReachedToLast, middlePages, pages])
  55. const isPreviousTruncable = React.useMemo(() => {
  56. // Is truncable if first value of middlePage is larger than last value of previousPages
  57. return middlePages[0] > previousPages[previousPages.length - 1] + 1
  58. }, [previousPages, middlePages])
  59. const isNextTruncable = React.useMemo(() => {
  60. // Is truncable if last value of middlePage is larger than first value of previousPages
  61. return middlePages[middlePages.length - 1] + 1 < nextPages[0]
  62. }, [nextPages, middlePages])
  63. return {
  64. currentPage,
  65. setCurrentPage,
  66. truncableText,
  67. truncableClassName,
  68. pages,
  69. hasPreviousPage,
  70. hasNextPage,
  71. previousPages,
  72. isPreviousTruncable,
  73. middlePages,
  74. isNextTruncable,
  75. nextPages,
  76. }
  77. }
  78. export default usePagination