Replies: 3 comments 7 replies
-
Can you elaborate on that? My first question was going to be what React Router should reasonably do when a dev specifies a path param with the same name as a search param? |
Beta Was this translation helpful? Give feedback.
-
The I think if you want to use runtime validation for search params this needs to be defined in the route module. What could go in route(path, file, {
id: "route-id",
searchParams: ["page", "order", "query"]
}) Then the router could use this to extract from the URL those search params, and you can receive them in a loader like this: export async function loader({ request, params, context }: Route.LoaderArgs {
params.routeParam // this is part of the pathname, typed as `string` (unless marked as optional)
params.page // from search params, typed as `string | null`
params.order // same as page
params.query // same as page
} You will still get const SearchParamsSchema = z.object({
page: z.coerce.number().nullable(),
order: z.enum(["asc", "desc"]).nullable(),
query: z.string().nullable()
})
export async function loader({ params }: Route.LoaderArgs) {
let searchParams = SearchParamsSchema.parse(params)
searchParams.page // this is now `number | null`
searchParams.order // this is now `"asc" | "desc"`
searchParams.query // this is still `string | null`
} |
Beta Was this translation helpful? Give feedback.
-
My main concern with the JS-first approach is that JS objects are not strictly compatible with the In particular, this is a perfectly valid querystring:
However, trying to map that to a JS object using A correct way of parsing/validating search params directly would be something like: const SearchParamsSchema = z.array(
z.union([
z.tuple([z.literal('category'), z.string()]),
z.tuple([z.literal('page'), z.coerce.number()]),
z.tuple([z.literal('page_size'), z.coerce.number()]),
z.tuple([z.string(), z.string()]), // catch everything else
])
); But that's... yeah. Not the prettiest or most pleasant to work with. My two cents: This mismatch presents challenges that are not within the scope of React Router's problem space. The platform has usable low-level abstractions ( (I am open to changing my mind though!) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Initial Idea
Define an optional
searchParams
schema inside eachroute()
entry.Keys merge into the existing
params
object, giving type-safety to bothhref()
and component props.Example
When user is already using flat routes you can augment the existing fs routes with ones with the search params, react router will deduplicate entries with the same path:
Usage
Motivation
href()
creation and component accessValidation
Powered by standard-schema, so any validator (Zod, Yup, Ajv, …) can be plugged in.
Error Handling
Validation failures bubble to the route’s existing error boundary.
Scope & Compatibility
searchParams
→ current behavior<Routes>
modeFAQ
params
instead of addingsearchParams
?href()
and component props unchanged.standard-schema
is just an adapter layer.Blockers
To extract the typescript code from the params schema defined using standard-schema we need to wait for jsonschema support in standard-schema first, or only support Zod initially.
Beta Was this translation helpful? Give feedback.
All reactions