11# use-query-state
22
3- A tiny React hook for typed URL query string state.
3+ Tiny, typed React URL query state. Co-locate state with your components and keep it in sync with the URL for shareable, deep‑linkable UIs.
4+
5+ [ ![ npm version] ( https://img.shields.io/npm/v/use-query-state.svg )] ( https://www.npmjs.com/package/use-query-state )
6+ [ ![ CI] ( https://github.com/gawryco/use-query-state/actions/workflows/ci.yml/badge.svg )] ( https://github.com/gawryco/use-query-state/actions/workflows/ci.yml )
7+ [ ![ License: MIT] ( https://img.shields.io/badge/License-MIT-green.svg )] ( LICENSE )
8+
9+ ## Features
10+
11+ - Typed builders: number, string, boolean, date, enum, json, custom
12+ - One-liner setup per key; React‑style setters with URL sync
13+ - Back/forward navigation support via ` popstate `
14+ - Tiny API, framework‑agnostic URL handling, SSR‑safe guards
15+ - ESM+CJS builds with type declarations
416
517## Install
618
@@ -12,32 +24,87 @@ npm i use-query-state
1224yarn add use-query-state
1325```
1426
15- ## Usage
27+ Peer dependency: ` react >= 17 ` .
28+
29+ ## Quick start
1630
1731``` tsx
1832import { useQueryState } from ' use-query-state' ;
1933
20- export function Example() {
21- const [page, setPage] = useQueryState <number >(' page' , {
22- parse : (v ) => (v ? Number (v ) : undefined ),
23- serialize : (v ) => (v == null ? null : String (v )),
24- defaultValue: 1 ,
25- history: ' push' ,
26- });
27-
28- return (
29- <button onClick = { () => setPage ((p ) => (p ?? 1 ) + 1 )} >Page: { page } </button >
30- );
34+ export function Counter() {
35+ const [n, setN] = useQueryState (' n' ).number (0 );
36+ return <button onClick = { () => setN ((v ) => v + 1 )} >Count: { n } </button >;
3137}
3238```
3339
34- ## API
40+ - Initializes from ` ?n=... ` if present; otherwise seeds the URL with the default.
41+ - Calling the setter updates both state and the URL.
42+
43+ ## API overview
44+
45+ ` useQueryState(key) ` returns a set of builder methods. Each returns ` [value, setValue] ` .
46+
47+ - ` number(defaultValue, opts?) `
48+ - ` opts ` : ` { min?: number; max?: number; step?: number } `
49+ - ` string(defaultValue, opts?) `
50+ - ` opts ` : ` { minLength?: number; maxLength?: number } `
51+ - ` boolean(defaultValue) `
52+ - Stored as ` '1' | '0' ` and accepts common truthy/falsy strings
53+ - ` date(defaultValue, opts?) `
54+ - Format ` yyyy-MM-dd ` (UTC); ` { min?: Date; max?: Date } `
55+ - ` enum(allowed, defaultValue) `
56+ - ` allowed: readonly string[] `
57+ - ` json(defaultValue, opts?) `
58+ - ` opts ` : ` { validate?, omitEmpty?, stringify?, parse? } `
59+ - ` custom(defaultValue, parse, format) `
60+ - Bring your own parsing/formatting logic
61+
62+ See full JSDoc/API in ` docs/ ` .
63+
64+ ## Examples
65+
66+ ``` tsx
67+ // String
68+ const [q, setQ] = useQueryState (' q' ).string (' ' );
69+
70+ // Boolean
71+ const [open, setOpen] = useQueryState (' open' ).boolean (false );
72+
73+ // Date (UTC yyyy-MM-dd)
74+ const [start, setStart] = useQueryState (' start' ).date (new Date (' 2024-01-01' ));
75+
76+ // Enum
77+ type Theme = ' light' | ' dark' ;
78+ const [t, setT] = useQueryState (' t' ).enum <Theme >([' light' , ' dark' ], ' light' );
79+
80+ // JSON with omitEmpty
81+ const [filters, setFilters] = useQueryState (' f' ).json ({ q: ' ' }, {
82+ omitEmpty : (v ) => v .q === ' ' ,
83+ });
84+ ```
85+
86+ ## SSR and environments
87+
88+ The hook guards access to ` window ` /` document ` . During SSR it returns the default value and no URL edits occur until hydration.
89+
90+ ## Navigation and events
91+
92+ - Listens for ` popstate ` and re-parses the URL to update state.
93+ - Dispatches a ` CustomEvent ` named ` qs:changed ` on ` window ` with ` { key, prev, next, params, source, ts } ` for diagnostics.
94+
95+ ## Type safety
96+
97+ The builders are typed. For advanced types use ` custom ` or ` json ` with a type guard.
98+
99+ ## Docs
100+
101+ - API docs: ` docs/api/ ` (generated from JSDoc)
102+ - Overview: ` docs/README.md `
103+
104+ ## Contributing
35105
36- - ` useQueryState(key, options) ` returns ` [value, setValue] ` .
37- - ` options.parse ` and ` options.serialize ` let you adapt non-string types.
38- - ` options.history ` : ` 'replace' | 'push' ` (default ` 'replace' ` ).
39- - ` options.defaultValue ` : used when param is absent.
106+ See [ CONTRIBUTING.md] ( CONTRIBUTING.md ) . Please note our [ Code of Conduct] ( CODE_OF_CONDUCT.md ) .
40107
41108## License
42109
43- MIT
110+ MIT — Copyright (c) 2025 Gawry & Co
0 commit comments