How to Use Url Query as State in React
Updated at
For this blog I wanted people to be able to search for articles and store the state in the url query.
React does not provide a hook for this out of the box, so I came up with one that is framework-agnostic.
The hook looks like the following:
0import {useEffect, useState} from 'react';12type QueryParamType = string | number | boolean | readonly string[] | readonly number[] | readonly boolean[] | null;34function useQueryState<T extends QueryParamType>(queryKey: string, initialValue: T) {5 const [state, setState] = useState<T>(initialValue);67 useEffect(() => {8 const getQueryParam = (key: string) => {9 const params = new URLSearchParams(window.location.search);10 return params.get(key);11 };1213 const queryValue = getQueryParam(queryKey);1415 if (queryValue !== null) {16 setState(queryValue as T);17 } else {18 const params = new URLSearchParams(window.location.search);19 if (initialValue) {20 params.set(queryKey, initialValue.toString());21 const newUrl = `${window.location.pathname}?${params.toString()}`;22 window.history.replaceState({}, '', newUrl);23 }24 }25 }, [queryKey, initialValue]);2627 const updateState = (newValue: T) => {28 setState(newValue);2930 const params = new URLSearchParams(window.location.search);31 if (newValue) {32 params.set(queryKey, newValue.toString());33 } else {34 params.delete(queryKey)35 }36 const newUrl = `${window.location.pathname}?${params.toString()}`;37 window.history.replaceState({}, '', newUrl);38 };3940 return [state, updateState] as const;41}4243export default useQueryState;
An example use case might be like this:
0typescript1const [appliedFilter, setAppliedFilter] = useQueryState<string>('q', '')
I am using this for my blog. It allows to filter the articles by title.