Strongly-typed way to manage URL parameters. Works with react-router (v6). Allows to strong-type parameters in routes and search.
yarn add react-router-url-params query-string
It's implied, that you have react-router
and react-router-dom
installed.
After that you could start using the createRoute
and useQueryParams
.
Create the route once, use it everywhere!
Just pass you URL pattern to createRoute function:
const productPageRoute = createRoute('/products/:id');
optionally you could specify a type for the parameters
const productPageRoute = createRoute('/products/:id', {id: RequiredNumberParam});
or you could even specify parameters that will go to search part (e.g. /products/3 ?sortBy=price), see below for details
const productPageRoute = createRoute('/products/:id', {id: RequiredNumberParam}, {sortBy: StringParam});
After that you could use it to
- Generate a link to that page
productPageRoute.link({id: 123}); // gives you /products/123
- Read parameter values inside your page (useParams hook with types)
const params = productPageRoute.useParams(); // gives you { id: 123 } with correct Typescript types
- Match url inside your page (useMatch hook with types)
const match = productPageRoute.useMatch();
// gives you: { params: { id: 123 }, pathname: '/products/123', pattern: '/products/:id' } with correct Typescript types
- Match url from arbitrary place (not a hook)
const matchAnywhere = productPageRoute.matchPath(window.location.pathname);
// gives you: { params: { id: 123 }, pathname: '/products/123', pattern: '/products/:id' } with correct Typescript types
- Use it in your Routes configuration:
<Routes>
<Route path={productPageRoute.route} element={/*your component here*/}/>
</Routes>
This is a port of use-query-params to react-router-v6.
Original API of useQueryParams
and useQueryParam
is preserved (and even serialization engine is reused).
The only change is that we are using useSearchParams of react-router to get and set query parameters.
Also, you don't need to wrap your app in <QueryParamProvider></QueryParamProvider>
, because we are tied to react-router API.
Since the API is the same, you could check the original docs or original demo (all credits go to pbeshai). I'm copying a part of original API description here for clarity:
URLUpdateType
has also been ported.
Example
import { useQueryParams, StringParam, NumberParam } from 'react-router-url-params';
// reads query parameters `foo` and `bar` from the URL and stores their decoded values
const [query, setQuery] = useQueryParams({ foo: NumberParam, bar: StringParam });
setQuery({ foo: 500 }); // will change the URL to '?foo=500'
setQuery({ foo: 123, bar: 'zzz' }, 'push'); // will change the URL to '?foo=123&bar=zzz'
// to unset or remove a parameter set it to undefined and use pushIn or replaceIn update types
setQuery({ foo: undefined }) // ?foo=123&bar=zzz becomes ?bar=zzz
// functional updates are also supported:
setQuery((latestQuery) => ({ foo: latestQuery.foo + 150 }))
See all param definitions from serialize-query-params. You can define your own parameter types by creating an object with an encode
and a decode
function. See the existing definitions for examples.
Examples in this table assume query parameter named qp
.
Param | Type | Example Decoded | Example Encoded |
---|---|---|---|
StringParam | string | 'foo' |
?qp=foo |
NumberParam | number | 123 |
?qp=123 |
ObjectParam | { key: string } | { foo: 'bar', baz: 'zzz' } |
?qp=foo-bar_baz-zzz |
ArrayParam | string[] | ['a','b','c'] |
?qp=a&qp=b&qp=c |
JsonParam | any | { foo: 'bar' } |
?qp=%7B%22foo%22%3A%22bar%22%7D |
DateParam | Date | Date(2019, 2, 1) |
?qp=2019-03-01 |
BooleanParam | boolean | true |
?qp=1 |
NumericObjectParam | { key: number } | { foo: 1, bar: 2 } |
?qp=foo-1_bar-2 |
DelimitedArrayParam | string[] | ['a','b','c'] |
?qp=a_b_c |
DelimitedNumericArrayParam | number[] | [1, 2, 3] |
?qp=1_2_3 |
You could add useQueryParams
support directly into createRoute
function as well! Just add a 3rd parameter to createRoute
, specifying the types of your search parameters:
const productPageRoute = createRoute('/products/:id', {id: RequiredNumberParam}, {sortBy: StringParam});
After that you could use .link
to generate a URL:
productPageRoute.link({id: 123}, {sortBy: 'price'});
// gives you /products/123?sortBy=price, and Typescript hints you about available parameters
and you could use .useParams
to read search parameters as well:
const params = productPageRoute.useParams();
// gives you { id: 123, queryParams: { sortBy: 'price' }, setQueryParams: (params: {sortBy: string}) => void } with correct Typescript types
const sortBy = params.queryParams.sortBy; // sortBy will be typed according to the definition in createRoute
params.setQueryParams({ sortBy: 'availabilityDate' }); // this will change the searchParam. Function argument will be correctly typed as well
Note that useMatch
and matchPath
do not have the queryParams
and setQueryParams
props. If you'd like them to be added, please create an issue!
Issues and Pull Requests are welcome.
For any kind of private consulting or support you could contact Artur Drobinskiy directly via email.