78 lines
1.8 KiB
TypeScript
78 lines
1.8 KiB
TypeScript
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
|
|
export type NavigateArgs = {
|
|
search: string
|
|
}
|
|
|
|
export type NavigateFunction = (args: NavigateArgs) => void
|
|
|
|
export type LocationObject = {
|
|
search: string
|
|
}
|
|
|
|
export type StorageOptions = {
|
|
enabled?: boolean
|
|
prefix?: string
|
|
namespace?: string
|
|
}
|
|
|
|
export type UsePagePaginationOptions = {
|
|
navigate: NavigateFunction
|
|
location: LocationObject
|
|
storage?: StorageOptions
|
|
steps?: number[]
|
|
}
|
|
|
|
export const usePagePagination = ({
|
|
navigate,
|
|
location,
|
|
storage = {
|
|
enabled: false,
|
|
prefix: 'app',
|
|
namespace: 'main',
|
|
},
|
|
steps = [5, 10, 20, 40, 80, 100],
|
|
}: UsePagePaginationOptions) => {
|
|
const queryParams = useMemo(
|
|
() => new URLSearchParams(location.search),
|
|
[location.search],
|
|
)
|
|
const page = Number(queryParams.get('page')) || 1
|
|
const storageSizeKey = useMemo(
|
|
() => `${storage.prefix}_${storage.namespace}_pagination_size`,
|
|
[storage],
|
|
)
|
|
const [size, setSize] = useState(
|
|
localStorage.getItem(storageSizeKey) && storage.enabled
|
|
? parseInt(localStorage.getItem(storageSizeKey) as string)
|
|
: steps[0],
|
|
)
|
|
|
|
const _setSize = useCallback(
|
|
(size: number) => {
|
|
setSize(size)
|
|
if (size && storage.enabled) {
|
|
localStorage.setItem(storageSizeKey, JSON.stringify(size))
|
|
}
|
|
},
|
|
[storageSizeKey, storage],
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (!queryParams.has('page')) {
|
|
queryParams.set('page', '1')
|
|
navigate({ search: `?${queryParams.toString()}` })
|
|
}
|
|
}, [queryParams, navigate])
|
|
|
|
const setPage = useCallback(
|
|
(page: number) => {
|
|
queryParams.set('page', String(page))
|
|
navigate({ search: `?${queryParams.toString()}` })
|
|
},
|
|
[queryParams, navigate],
|
|
)
|
|
|
|
return { page, size, steps, setPage, setSize: _setSize }
|
|
}
|