Custom QS Library
By default, createQsUtils() uses the browser’s native URLSearchParams. You can swap in any query string library by passing a qs option.
Using the qs library
Section titled “Using the qs library”import { parse, stringify } from "qs";
const qsUtils = createQsUtils({ qs: { parse: (search) => parse(search, { ignoreQueryPrefix: true }), stringify: (values) => stringify(values), },});Using query-string
Section titled “Using query-string”import queryString from "query-string";
const qsUtils = createQsUtils({ qs: { parse: (search) => queryString.parse(search), stringify: (values) => queryString.stringify(values), },});Interface
Section titled “Interface”The qs option expects:
{ parse: (search: string) => Record<string, unknown>; stringify: (values: Record<string, unknown>) => string;}parse receives the raw location.search string (with or without ? depending on your library).
stringify should return the query string without the leading ?.
Why use a custom library?
Section titled “Why use a custom library?”| Feature | URLSearchParams | qs / query-string |
|---|---|---|
| Nested objects | No | Yes |
| Array formats | key=a&key=b only | key[]=a, key[0]=a, comma-separated |
| Date serialization | Manual | Configurable |
| Bundle size | 0 KB (built-in) | ~5-10 KB |
Live demo
Section titled “Live demo”Both sides share the same URL. Edit values on either side and observe how each library parses the same search string differently:
Custom QS Library: Array Format Comparison
URLSearchParams
| (native) | (empty) |
qs
| (default) | (empty) |
| indices | (empty) |
| brackets | (empty) |
| repeat | (empty) |
| comma | (empty) |
query-string
| (default) | (empty) |
| bracket | (empty) |
| index | (empty) |
| comma | (empty) |
| bracket-separator | (empty) |
| colon-list-separator | (empty) |
| none | (empty) |
| separator (|) | (empty) |