-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathuseSearchParams.ts
executable file
·56 lines (48 loc) · 1.58 KB
/
useSearchParams.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import { ref, onMounted, onUnmounted, Ref } from '@src/api'
import {
patchHistoryMethodsOnce,
normalizeEntriesData
} from '@src/shared/utils'
const normalizeParams = (urlParamsObj: { [key: string]: string }) => (
paramAcc: any,
param: string
) => {
paramAcc[param] = param in urlParamsObj ? urlParamsObj[param] : null
return paramAcc
}
const getUrlParams = (parameters: string[]) => {
const urlParamsObj = normalizeEntriesData(
Array.from(new URLSearchParams(location.search).entries())
)
return parameters.reduce(normalizeParams(urlParamsObj), {})
}
export function useSearchParams<T extends string>(
parameters: T[],
runOnMount = true
) {
const searchParams = ref(
parameters.reduce(normalizeParams({}), {} as { [key in T]: any })
)
const isTracking = ref(false)
const handleParamsChange = () =>
(searchParams.value = getUrlParams(parameters))
const start = () => {
if (isTracking.value) return
patchHistoryMethodsOnce()
handleParamsChange()
window.addEventListener('popstate', handleParamsChange)
window.addEventListener('pushstate', handleParamsChange)
window.addEventListener('replacestate', handleParamsChange)
isTracking.value = true
}
const stop = () => {
if (!isTracking.value) return
window.removeEventListener('popstate', handleParamsChange)
window.removeEventListener('pushstate', handleParamsChange)
window.removeEventListener('replacestate', handleParamsChange)
isTracking.value = false
}
onMounted(() => runOnMount && start())
onUnmounted(stop)
return { searchParams, isTracking, start, stop }
}