Bits and bytes of code
Bytes is my collection of short-form posts, tips, and things I learn as I build software.
Bytes is my collection of short-form posts, tips, and things I learn as I build software.
The useParams and useSearchParams hooks from React Router are critical
when working with dynamic routes, however they have some sharp edges when
used with TypeScript. With a small amount of additional code, we can make
it much easier to work with params.
The two primary issues with useParams (and useSearchParams) are:
Let’s solve these two problems by creating a custom useStrictParams hook
which will both mark params as required as well as handle type conversion
for us.
import { useParams, useSearchParams } from "react-router-dom"
type TypeDef = Record<string, NumberConstructor | StringConstructor>
type StrictParams<T> = {
To use this new hook, we can simply call it and provide an object which specifies the types of our params. We cannot simply use generic types since the types are not only used to specify the available params, but in the case of numbers, they also convert the runtime values to the correct types. While this example only uses strings and numbers, adding support for booleans or even dates would be very simple.
const { userId, age } = useStrictParams({ userId: String, age: Number })We can do the same with search params with the following code:
export function useStrictSearchParams<T extends TypeDef>(
typedef: T,
): [StrictParams<T>, (params: URLSearchParams) => void] {
const [searchParams, setSearchParams] = useSearchParams()
return [toStrict([...searchParams.
This idea could be expanded on to include other features such as converting
arrays of search params via the Array type, or even allowing undefined
values by creating a Optional type like this:
useStrictParams({ query: Optional(String) })