React Hooks
useQueryParamsState
Learn how to sync React state with URL search parameters
September 06, 2021
Loading viewsimport { useEffect, useState } from 'react';
export const useQueryParamsState = (param) => {
const [value, setValue] = useState(() => {
if (typeof window === 'undefined') return '';
const { search } = window.location;
const searchParams = new URLSearchParams(search);
return searchParams.has(param) ? searchParams.get(param) : '';
});
useEffect(() => {
const newUrl = new URL(window.location);
if (value) {
newUrl.searchParams.set(param, value);
} else {
newUrl.searchParams.delete(param);
}
window.history.replaceState(window.history.state, '', newUrl);
}, [param, value]);
return [value, setValue];
};
Context
It's a common practice to append search params to a URL so that the website could use that information to perform actions like searching, filtering and sorting.
This is a hook for text value searching by syncing your input state from React.useState
with the URL search params. You can type in the input field or edit the search params in the URL. Then you can use the state to perform whatever side effects you want.
Usage
const FRUITS = ['apple', 'orange', 'watermelon'];
const App = () => {
const [value, setValue] = useQueryParamsState('search');
return (
<>
<input
type="search"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<ul>
{FRUITS.filter((f) => f.startsWith(value)).map((f) => (
<li key={f}>{f}</li>
))}
</ul>
</>
);
};
Explanation
The hook takes an argument which the key you wish to refer to in the URL search params. For example, if you would like to search using ?q=someValue
, then just call useQueryParamsState('q')
.
We are lazy initializing the value state by passing a function to useState
. Kent C. Dodds wrote an article about this practice. The function grabs and initializes the state with any search params in the URL. This way we can dynamically route and search without relying on an input field.
The useEffect
helps us to update the URL without refreshing by using history.replaceState
.