Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

use-document-list-query-state.ts 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { type ReadonlyURLSearchParams, usePathname, useRouter, useSearchParams } from 'next/navigation'
  2. import { useCallback, useMemo } from 'react'
  3. export type DocumentListQuery = {
  4. page: number
  5. limit: number
  6. keyword: string
  7. }
  8. const DEFAULT_QUERY: DocumentListQuery = {
  9. page: 1,
  10. limit: 10,
  11. keyword: '',
  12. }
  13. // Parse the query parameters from the URL search string.
  14. function parseParams(params: ReadonlyURLSearchParams): DocumentListQuery {
  15. const page = Number.parseInt(params.get('page') || '1', 10)
  16. const limit = Number.parseInt(params.get('limit') || '10', 10)
  17. const keyword = params.get('keyword') || ''
  18. return {
  19. page: page > 0 ? page : 1,
  20. limit: (limit > 0 && limit <= 100) ? limit : 10,
  21. keyword: keyword ? decodeURIComponent(keyword) : '',
  22. }
  23. }
  24. // Update the URL search string with the given query parameters.
  25. function updateSearchParams(query: DocumentListQuery, searchParams: URLSearchParams) {
  26. const { page, limit, keyword } = query || {}
  27. const hasNonDefaultParams = (page && page > 1) || (limit && limit !== 10) || (keyword && keyword.trim())
  28. if (hasNonDefaultParams) {
  29. searchParams.set('page', (page || 1).toString())
  30. searchParams.set('limit', (limit || 10).toString())
  31. }
  32. else {
  33. searchParams.delete('page')
  34. searchParams.delete('limit')
  35. }
  36. if (keyword && keyword.trim())
  37. searchParams.set('keyword', encodeURIComponent(keyword))
  38. else
  39. searchParams.delete('keyword')
  40. }
  41. function useDocumentListQueryState() {
  42. const searchParams = useSearchParams()
  43. const query = useMemo(() => parseParams(searchParams), [searchParams])
  44. const router = useRouter()
  45. const pathname = usePathname()
  46. // Helper function to update specific query parameters
  47. const updateQuery = useCallback((updates: Partial<DocumentListQuery>) => {
  48. const newQuery = { ...query, ...updates }
  49. const params = new URLSearchParams()
  50. updateSearchParams(newQuery, params)
  51. const search = params.toString()
  52. const queryString = search ? `?${search}` : ''
  53. router.push(`${pathname}${queryString}`, { scroll: false })
  54. }, [query, router, pathname])
  55. // Helper function to reset query to defaults
  56. const resetQuery = useCallback(() => {
  57. const params = new URLSearchParams()
  58. updateSearchParams(DEFAULT_QUERY, params)
  59. const search = params.toString()
  60. const queryString = search ? `?${search}` : ''
  61. router.push(`${pathname}${queryString}`, { scroll: false })
  62. }, [router, pathname])
  63. return useMemo(() => ({
  64. query,
  65. updateQuery,
  66. resetQuery,
  67. }), [query, updateQuery, resetQuery])
  68. }
  69. export default useDocumentListQueryState