Files
Compass/web/hooks/use-persistent-query-state.ts
2026-02-23 14:48:03 +01:00

53 lines
1.6 KiB
TypeScript

import {debounce, pickBy} from 'lodash'
import {useRouter} from 'next/router'
import {useEffect, useState} from 'react'
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})]
}