Added
- Add
configure()
for configuring types parser globally.
- Allow to pass a custom parser as a second argument to all built-in types.
- Expose params kind (
"pathname" | "search" | "hash"
) for custom parsers to use.
- Add pathless routes and route composition API.
// Instead of route(':id', { params: { id: number() }, searchParams: { page: number() } })
const fragment = route({ params: { id: number() }, searchParams: { page: number() } });
// Instead of types(FRAGMENT)({searchParams: { query: string() }})
const myRoute = route({
path: "my-path/:id",
compose: [fragment],
searchParams: { query: string() },
});
const { id } = useTypedParams(fragment);
const [{ page }] = useTypedSearchParams(fragment);
Changed
union()
now accepts enums and readonly (as const
) objects.
union()
now properly infers values from an inline array without as const
.
- Pathname params without explicit types now use
string()
and string().defined()
for optional and required params respectively instead of custom code.
- State can now optionally be typed as a whole, so non-object states can now be typed.
- Optional splats are now explicitly forbidden (they stopped working in React Router v6.9.0).
- Routes without pathname/search/state params now accept non-empty object as these params.
- Breaking:
union()
no longer accepts its values as multiple arguments.
- Breaking: Types for pathname
params
are now stricter and don't allow params which are not specified in the path pattern. This also fixes autocomplete for such params.
- Breaking: A
$
is added to all fields of a route object, so now child routes can start with a lowercase character and use basically any naming scheme (unless they start with a $
, which is forbidden).
- Breaking: The
path
and relativePath
route fields were squashed into the $path()
function. It returns an absolute path pattern by default or a relative path pattern if the relative
option is set to true
.
- Breaking: The
types
field is renamed to $spec
, and it now also contains an unmodified path
option of the route.
- Breaking: Naming scheme was changed from
getPlain
/getTyped
to serialize
/deserialize
for clarity.
- Breaking: Path and state generation API is changed.
$buildPath
(formerly buildPath
) now accepts all params as a single argument. Signatures of all build*
functions were updated accordingly.
$buildPathname
is added.
buildRelativePath
is removed, and instead $buildPath
and $buildPathname
now accept a relative
option.
getUntypedParams
, getUntypedSearchParams
, and getUntypedState
were removed. Instead, $buildPath
, $buildSearch
, $serializeSearchParams
, and $buildState
now accept untypedSearchParams
or untypedState
options where applicable. When provided, the corresponding untyped parts are added to the resulting path (the search part) or state. The corresponding option in useTypedSearchParams
is also renamed.
$serializeSearchParams
(formerly getPlainSearchParams
) now returns a URLSearchParams
instance for consistency with the rest of the API.
- Breaking:
route
API is changed. It now accepts a single argument with optional types, path, composed routes and children. By default, path is undefined
(which means a pathless route).
- Breaking: Hash should now be specified as an array of strings or a type. Empty array now means "nothing" instead of "any string". For example:
hashValues('about', 'info')
=> ['about', 'info']
hashValues()
=> string()
- Default:
[]
- You can also use other types, like
number().default(-1)
- Breaking: Array types like
string().array()
now filter undefined
values upon parsing. The previous behavior broke a common pattern of changing a subset of search parameters:
const FRAGMENT = route({ searchParams: { pages: number().array(), query: string() } });
const [{ pages, query }, setTypedSearchParams] = useTypedSearchParams(FRAGMENT);
setTypedSearchParams((prevParams) => ({
// Previously, prevParams.pages would be (number|undefined)[],
// which is not assignable to number[].
...prevParams,
query: "hi",
}));
- Breaking: Similarly,
undefined
keys are now omitted from all parsed params to match how there are no such keys in raw params
from React Router. The reason this behavior was originally introduced is not relevant anymore.
- Breaking:
$
no longer prevents pathname types inheritance.
- Breaking: Some types are changed for convenience and readability.
- Breaking: The minimal required version of TS is now
v5.0
with strict
mode enabled.
- Breaking: The minimal required version of React Router is now
v7.0
.
- Breaking: CommonJS is now used by default, similarly to React Router.
Removed
- Breaking: Removed
/dom
and /native
entry points. Use the main entry point instead.
- Breaking: Removed all deprecated features.
- Breaking: Removed
hashValues()
. Pass an array of strings or a type instead.
- Breaking: Removed
types()
. Use composition API instead.