import {debounce, pickBy} from 'lodash' import {useRouter} from 'next/router' import {useEffect, useState} from 'react' type UrlParams = Record // for updating multiple query params export const usePersistentQueriesState = ( defaultValue: T, ): [T, (newState: Partial) => 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) => { // 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 = ( 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})] }