Created
May 20, 2021 22:24
-
-
Save tomfa/9bf850bbaeb421c77d2b1bd2a158ae10 to your computer and use it in GitHub Desktop.
NextJS string state in URL query param
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import useQueryString from './useQueryString' | |
export const Component = () => { | |
const [cat, setCat] = useQueryString<string>({ | |
key: 'cat', | |
defaultValue: 'Robert Paulson', | |
}); | |
return <h1>His name is <strong>{cat}</strong></h1> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback, useEffect, useMemo, useState } from 'react'; | |
import { useRouter } from 'next/router'; | |
import { getQueryStringValue } from './utils.query'; | |
interface Props { | |
key: string; | |
defaultValue: string; | |
} | |
function useQueryString({ | |
key, | |
defaultValue, | |
}: Props): [string, React.Dispatch<React.SetStateAction<string>>] { | |
const router = useRouter(); | |
const [loading, setLoading] = useState(false); | |
const [value, setValue] = useState<string>(() => { | |
const queryParamValue = getQueryStringValue(router, key); | |
return queryParamValue || defaultValue; | |
}); | |
const onSetValue = useCallback( | |
async (newValue: string) => { | |
setLoading(true); | |
setValue(newValue); | |
// use router.push if you want to edit browser history | |
await router.replace({ query: { ...router.query, [key]: newValue } }, undefined, { | |
shallow: true, | |
}); | |
setLoading(false); | |
}, | |
[router, key], | |
); | |
const queryParamValue = router.query[key]; | |
const queryParamMatches = useMemo(() => { | |
if (!router.isReady) { | |
return false; | |
} | |
if (!queryParamValue) { | |
const valueIsUndefinedAsQuery = value === undefined || value === defaultValue; | |
return valueIsUndefinedAsQuery; | |
} | |
return queryParamValue === value; | |
}, [value, queryParamValue, defaultValue, router.isReady]); | |
// Update value on url change | |
useEffect(() => { | |
if (!router.isReady || queryParamMatches || loading) { | |
return; | |
} | |
setValue(queryParamValue || defaultValue); | |
}, [setValue, queryParamMatches, defaultValue, queryParamValue router.isReady, loading]); | |
return [value, onSetValue]; | |
} | |
export default useQueryString; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qs from 'query-string'; // Note: added 3rd party lib | |
import { NextRouter } from 'next/router'; | |
export const getQueryStringValue = (router: NextRouter, key: string) => { | |
if (router.isReady) { | |
return router.query[key]; | |
} | |
if (typeof window !== 'undefined') { | |
const values = qs.parse(window.location.search); | |
return values[key]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment