import { useState , useCallback } from 'react' ; import { navigate } from './navigate' ; import { isNode , getSsrPath } from './node' ; import { getCurrentPath , getCurrentHash , useLocationChange } from './path' ; export interface QueryParam { [ key ] : any ; } export interface setQueryParamsOptions { replace ? : boolean ; } export function useQueryParams < T extends QueryParam > ( parseFn = parseQuery , serializeFn = serializeQuery ) { const [ querystring , setQuerystring ] = useState ( getQueryString ( ) ) ; const setQueryParams = useCallback ( ( params , { replace = true } = { } ) => { let path = getCurrentPath ( ) ; params = replace ? params : { ... parseFn ( querystring ) , ... params } ; const serialized = serializeFn ( params ) . toString ( ) ; if ( serialized ) path += '?' + serialized ; if ( ! replace ) path += getCurrentHash ( ) ; navigate ( path ) ; } , [ querystring , parseFn , serializeFn ] ) ; const updateQuery = useCallback ( ( ) => setQuerystring ( getQueryString ( ) ) , [ ] ) ; useLocationChange ( updateQuery ) ; return [ parseFn ( querystring ) , setQueryParams ] ; } function parseQuery < T extends QueryParam > ( querystring ) { const q = new URLSearchParams ( querystring ) ; return Object . fromEntries ( q . entries ( ) ) as T ; } function serializeQuery < T extends QueryParam > ( queryParams ) { return new URLSearchParams ( Object . entries ( queryParams ) . filter ( ( [ , v ] ) => v !== null ) ) . toString ( ) ; } export function getQueryString ( ) { if ( isNode ) { const ssrPath = getSsrPath ( ) ; const queryIndex = ssrPath . indexOf ( '?' ) ; return queryIndex === - 1 ? '' : ssrPath . substring ( queryIndex + 1 ) ; } return window . location . search ; }