use-route-query
Built-in QueryParsers.
| Package | @vizejs/composable/use-route-query |
| Own the source | vize lib pull composable:use-route-query |
| Runtime exports | queryParsers, oneOf, useRouteQuery, useRouteParams |
| Gzip budget | 1536 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { queryParsers, oneOf, useRouteQuery, useRouteParams } from "@vizejs/composable/use-route-query";
Try it
Keep the selected tab in the URL query
Read and write one typed query parameter so a view can be shared and restored.
What to observe: Choose pricing and the query becomes tab=pricing. Choose overview to remove it, because it is the default.
This example uses a local route object; in an app pass useRoute() and navigate with router.replace({ query }). oneOf rejects unknown values.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { computed, reactive } from "vue";
import { oneOf, useRouteQuery } from "@vizejs/composable/use-route-query";
// In an app, pass `useRoute()` and navigate with `router.replace({ query })`.
const route = reactive({ params: {}, query: {} as Record<string, string> });
const queryText = computed(() => new URLSearchParams(route.query).toString() || "(none)");
const tab = useRouteQuery(route, "tab", {
parse: oneOf(["overview", "pricing", "faq"] as const),
default: "overview",
navigate: (query) => {
route.query = { ...(query as Record<string, string>) };
},
});
</script>
<template>
<div class="composable-example">
<p>Keep the selected tab in the URL query so the view can be shared and restored.</p>
<div role="tablist" aria-label="Product sections">
<button
v-for="name in ['overview', 'pricing', 'faq'] as const"
:key="name"
role="tab"
type="button"
:aria-selected="tab === name"
@click="() => (tab = name)"
>
{{ name }}
</button>
</div>
<output aria-live="polite">Query: {{ queryText }}</output>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
oneOf |
state | experimental | safe | stable | none | web, server, worker, native, desktop, terminal | — | — |
useRouteQuery |
state | experimental | safe | stable | none | web, server, worker, native, desktop, terminal | — | — |
useRouteParams |
state | experimental | safe | stable | none | web, server, worker, native, desktop, terminal | — | — |
API
queryParsers
Built-in QueryParsers.
const queryParsers
oneOf
Parser accepting only the given literal values.
function oneOf<const Values extends readonly string[]>( values: Values, ): QueryParser<Values[number]>
useRouteQuery(route, "sort", { parse: oneOf(["new", "top"]), default: "new" });
useRouteQuery
Typed, optionally writable view of one query parameter. The value type is inferred from parse and default: with a default the ref never holds undefined. Pass navigate to make the ref writable; writes build the next query (keeping every other key), drop the key when the value equals the default, and hand it to navigate, which is where the router integration pushes or replaces the URL. Works with any route object exposing query, including @vizejs/router's RouteMatch. Pure derived state: SSR-safe and hydration-stable (it reads the matched route only).
function useRouteQuery( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: StringQueryOptions & { readonly default: string; readonly navigate: (query: RouteQueryRecord) => void; }, ): WritableComputedRef<string>
const page = useRouteQuery(match, "page", {
parse: queryParsers.integer,
default: 1,
navigate: (query) => navigateTo(router.resolve(match.value.name, match.value.params, { query })),
});
page.value += 1;
useRouteQuery
function useRouteQuery( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: StringQueryOptions & { readonly navigate: (query: RouteQueryRecord) => void }, ): WritableComputedRef<string | undefined, string | undefined>
useRouteQuery
function useRouteQuery( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: StringQueryOptions & { readonly default: string }, ): ComputedRef<string>
useRouteQuery
function useRouteQuery( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options?: StringQueryOptions, ): ComputedRef<string | undefined>
useRouteQuery
function useRouteQuery<Value>( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: UseRouteQueryOptions<Value> & { readonly default: NoInfer<Value>; readonly navigate: (query: RouteQueryRecord) => void; }, ): WritableComputedRef<Value>
useRouteQuery
function useRouteQuery<Value>( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: UseRouteQueryOptions<Value> & { readonly navigate: (query: RouteQueryRecord) => void }, ): WritableComputedRef<Value | undefined, Value | undefined>
useRouteQuery
function useRouteQuery<Value>( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: UseRouteQueryOptions<Value> & { readonly default: NoInfer<Value> }, ): ComputedRef<Value>
useRouteQuery
function useRouteQuery<Value>( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: UseRouteQueryOptions<Value>, ): ComputedRef<Value | undefined>
useRouteQuery
function useRouteQuery( route: MaybeRefOrGetter<RouteLocationLike>, key: string, options: ErasedQueryOptions = {}, ): ComputedRef<unknown> | WritableComputedRef<unknown>
useRouteParams
Typed view of the matched route's path params. Without a key, returns all params (typed from the route table when the route comes from @vizejs/router). With a key, returns that param; with a parser, the parsed value. Pure derived state: SSR-safe.
function useRouteParams<Route extends RouteLocationLike>( route: MaybeRefOrGetter<Route>, ): ComputedRef<RouteParamsOf<Route>>
const params = useRouteParams(match); // ComputedRef<{ readonly id: string }>
const id = useRouteParams(match, "id", Number); // ComputedRef<number>
useRouteParams
function useRouteParams<Route extends RouteLocationLike, Key extends keyof Route["params"]>( route: MaybeRefOrGetter<Route>, key: Key, ): ComputedRef<Route["params"][Key]>
useRouteParams
function useRouteParams< Route extends RouteLocationLike, Key extends keyof Route["params"], Value, >( route: MaybeRefOrGetter<Route>, key: Key, parse: (raw: Route["params"][Key]) => Value, ): ComputedRef<Value>
useRouteParams
function useRouteParams( route: MaybeRefOrGetter<RouteLocationLike>, ...args: readonly [] | readonly [PropertyKey] | readonly [PropertyKey, (raw: unknown) => unknown] ): ComputedRef<unknown>
Types
RouteLocationLike
Structural subset of a matched route. @vizejs/router's RouteMatch satisfies it, so its inferred params type flows through without this package depending on the router.
| Member | Type | Description |
|---|---|---|
params |
object |
Decoded path params. |
query |
RouteQueryRecord |
Parsed query. |
UseRouteQueryOptions
Options for useRouteQuery.
| Member | Type | Description |
|---|---|---|
parse? |
QueryParser<Value> |
Converts the raw value. |
serialize? |
QuerySerializer<Value> |
Converts a written value back into the query. |
navigate? |
(query: RouteQueryRecord) => void |
Performs the navigation for a write, receiving the complete next query. Without it the returned ref is read-only. |
omitDefault? |
boolean |
Remove the key instead of writing it when the value equals the default. |