Skip to content

Quick Start

import { useStore } from "@nanostores/react";
import { createQsUtils } from "@vp-tw/nanostores-qs";
import * as presets from "@vp-tw/nanostores-qs/presets";
const qsUtils = createQsUtils();
// Single parameter with a preset — defaults to 1 instead of NaN
const pageStore = qsUtils.createSearchParamStore("page", presets.integer({ default: 1, min: 0 }));
// Multiple parameters with presets
const filters = qsUtils.createSearchParamsStore({
page: presets.integer({ default: 1, min: 0 }),
sort: presets.enum(["newest", "oldest", "popular"]),
showArchived: presets.boolean(),
});
function Filters() {
const page = useStore(pageStore.$value); // number (1 when absent)
const values = useStore(filters.$values); // { page, sort, showArchived }
return (
<div>
<p>Page: {page}</p>
<button
type="button"
onClick={() => filters.updateAll({ ...values, page: 1, sort: "popular" })}
>
Popular first
</button>
</div>
);
}
  1. createQsUtils() creates a reactive utility that listens to URL changes.
  2. Presets like integer() handle type conversion (decode from URL string, encode back).
  3. Stores ($value, $values) are nanostores — use your framework’s binding to subscribe.
  4. update() pushes a new browser history entry with the updated URL.
  5. .dry() returns the next search string without changing the URL — useful for building links.