Strongly typed, routing-library agnostic react hook to use and manipulate query params.
- Strongly Typed
- Uses Browser's DOM History API
- Functional Updates
- Re-renders only when the params you accessed changes.
# npm
npm install --save react-use-query-params
# pnpm
pnpm add react-use-query-params
Behaves very similar to React's useState
import useQueryParams from "react-use-query-params";
function App() {
const [params, setParams] = useQueryParams();
const clickHandler = () => {
setParams({
tomato: 'RED'
});
};
return (
<>
<div>
{params.tomato.length // parameters are always arrays of strings
? params.tomato[0]
: null}
</div>
<button onClick={clickHandler}>Update</button>
</>
);
}
If you don't want to accidentally access the wrong query param key, you can pass an object as the first generic type argument.
interface QueryParams {
tomato: string;
potato: string;
}
const [params, setParams] = useQueryParams<QueryParams>();
params.tomato; // ok
params.potato; // ok
params.mango; // Type Error
You can send a string array in any key to setParams
setParams({
tomato: ['RED', 'ROUND']
});
Sending true
as the second argument to setParams
will use .replaceState()
instead of .pushState()
setParams({
tomato: 'RED'
}, true);
Similar to React's useState
, you can pass a function to setParams
.
const [params, setParams] = useQueryParams<QueryParams>();
setParams((params) => {
return {
...params,
tomato: 'GREEN'
};
});
The params
object is actually a proxy that tracks which query params the rest of your code
is interested in. This allows the library to only trigger re-renders those parameters change.
The proxy also accounts for iteration (for (const key in params) { ... }
,
Object.keys(params)
, Object.values(params)
, etc). That means when you iterate
over the available keys, if a new query param is added, the component will re-render.
The same is true if the query param is removed even if you didn't access the param's value.
MIT