Files
Compass/web/hooks/use-persistent-query-state.ts
2025-08-27 21:30:05 +02:00

56 lines
1.6 KiB
TypeScript

import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { pickBy, debounce } from 'lodash'
type UrlParams = Record<string, string | undefined>
// for updating multiple query params
export const usePersistentQueriesState = <T extends UrlParams>(
defaultValue: T
): [T, (newState: Partial<T>) => void, boolean] => {
const [state, setState] = useState(defaultValue)
const router = useRouter()
const [ready, setReady] = useState(false)
// On page load, initialize the state to the current query params once.
useEffect(() => {
if (router.isReady) {
setState({ ...defaultValue, ...router.query })
setReady(true)
}
}, [router.isReady])
const setRouteQuery = debounce((newQuery: string) => {
const { pathname } = router
const q = newQuery ? '?' + encodeURI(newQuery) : ''
router.replace(pathname + q)
}, 200)
const updateState = (update: Partial<T>) => {
// Include current query because it might have been updated by another component.
const newState = { ...state, ...router.query, ...update } as T
setState(newState)
const query = pickBy(newState, (v) => v)
const newQuery = Object.keys(query)
.map((key) => `${key}=${query[key]}`)
.join('&')
setRouteQuery(newQuery)
}
return [state, updateState, ready]
}
export const usePersistentQueryState = <K extends string>(
key: K,
defaultValue: string
): [string | undefined, (newState: string) => void] => {
const [state, updateState] = usePersistentQueriesState({
[key]: defaultValue,
})
return [
state ? state[key] : undefined,
(newState: string) => updateState({ [key]: newState }),
]
}