qwik-querysignal for Qwik
Type-safe search params state manager for Qwik - Like useSignal()
, but stored in the URL query string.
This project was inspired by nuqs library for Next.js
- 🧘♀️ Simple: the URL is the source of truth
- 🕰 Reload, Replace, append Route History to use the Back button to navigate state updates
- ⚡️ Built-in serializers for common state types (integer, float, boolean, Date, and more)
- 📦 Support for working with arrays
- ⌛️ new: Support for debounced query state changes.
useQuerySignal()
, useQueryStringSignal()
and useQueryArraySignal()
track current route url search-params for any changes and vice versa tracks the returned signal state and updates the search-params.
it uses Qwik's builtin useNavigation()
under the hood to navigate to the updated url
pnpm add qwik-querysignal
yarn add qwik-querysignal
npm install qwik-querysignal
import { component$ } from "@builder.io/qwik";
import {
useQueryStringSignal,
} from "qwik-querysignal";
export default component$(() => {
const sortBy = useQueryStringSignal("sortBy", "desc", {
replaceState: true,
});
return (
<div class="m-12 flex flex-col gap-1">
<h1 class="text-3xl">Hello👋</h1>
<input
class="rounded-md border-2 border-blue-400 px-2 py-1 hover:border-blue-700"
value={sortBy.value}
onInput$={(e) => (sortBy.value = e.target?.value)}
/>
</div>
);
});
If your state type is not a string, you must pass a serializer in the second argument object.
We provide builtin serializers for common and more advanced object types:
- String:
import { parseAsString } from "qwik-querysignal"
const search = useQueryStringSignal("search", "default", {
replaceState: true,
})
// or with passing a serializer manually
const search = useQuerySignal("search", parseAsString("default"))
- Boolean:
import { parseAsBoolean } from "qwik-querysignal"
const checked = useQuerySignal("checked", parseAsBoolean())
- Numbers:
import { parseAsInteger, parseAsFloat, parseAsHex } from "qwik-querysignal"
const count = useQuerySignal("count", parseAsInteger())
const sum = useQuerySignal("sum", parseAsFloat())
const hex = useQuerySignal("hex", parseAsHex("FFA1"))
- Dates:
import {
parseAsIsoDateTime,
parseAsDateTimeFormatted,
parseAsTimestamp,
} from "qwik-querysignal"
const date = useQuerySignal("date", parseAsIsoDateTime())
const today = useQuerySignal("today", parseAsDateTimeFormatted("yyyy-MM-dd"))
const timestamp = useQuerySignal("ts", parseAsTimestamp())
- Objects as JSON:
import { parseAsJson } from "qwik-querysignal"
const options = useQuerySignal(
"options",
parseAsJson({ sortBy: "id", desc: false }),
)
- Enums
import { parseAsStringEnum } from "qwik-querysignal"
const sortBy = useQuerySignal(
"sortBy",
parseAsStringEnum(["asc", "desc", "auto"]),
)
to work with array use useQueryArraySignal()
, and provide a separator
and itemSerializer
:
import { useQueryArraySignal, parseAsString } from "qwik-querysignal"
const names = useQueryArraySignal("names", ",", parseAsString())
useQuerySignal()
accepts an optional options
third parameter to tweak route navigation behavior after query state change.
const search = useQuerySignal("search", parseAsString(), {
replaceState: true, // Replace history
forceReload: false, // Reload page on state change
scroll: true, // Preserve scroll state
})
useQuerySignalDebounced
and useQueryArraySignalDebounced
can be used to include debounce filter to delay navigation until x milliseconds has passed from the last state change.
import { useQuerySignalDebounced } from "qwik-querysignal"
const [search, searchDebounced] = useQuerySignalDebounced(
"search",
parseAsString(),
500 /*in milliseconds*/,
)