Type-safe search params state manager for Next.js - Like React.useState, but stored in the URL query string
npx @tessl/cli install tessl/npm-nuqs@1.20.00
# nuqs
1
2
nuqs is a type-safe state management library for Next.js that synchronizes React component state with URL query parameters. It provides React hooks that work like `useState` but store values in the URL query string, enabling shareable URLs and maintaining state across page refreshes.
3
4
## Package Information
5
6
- **Package Name**: nuqs
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install nuqs`
10
11
## Core Imports
12
13
```typescript
14
import { useQueryState, useQueryStates, parseAsInteger } from "nuqs";
15
```
16
17
For server-side usage:
18
19
```typescript
20
import { createSearchParamsCache, parseAsString } from "nuqs/server";
21
```
22
23
## Basic Usage
24
25
```typescript
26
import { useQueryState, parseAsInteger } from "nuqs";
27
28
export default function SearchPage() {
29
const [search, setSearch] = useQueryState('q');
30
const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1));
31
32
return (
33
<div>
34
<input
35
value={search || ''}
36
onChange={(e) => setSearch(e.target.value)}
37
placeholder="Search..."
38
/>
39
<p>Current page: {page}</p>
40
<button onClick={() => setPage(page + 1)}>Next Page</button>
41
</div>
42
);
43
}
44
```
45
46
## Architecture
47
48
nuqs is built around several key components:
49
50
- **Query State Hooks**: `useQueryState` and `useQueryStates` provide React state management synchronized with URL query parameters
51
- **Parser System**: Type-safe parsers for converting between query strings and typed values (integers, booleans, dates, arrays, etc.)
52
- **Server-Side Cache**: Server components can access and parse query parameters with `createSearchParamsCache`
53
- **Synchronization Engine**: Cross-hook synchronization and external URL change detection
54
- **URL Serialization**: Utilities for generating query strings from typed values
55
56
## Capabilities
57
58
### Single Query State Management
59
60
Core hook for managing individual query parameters with type safety and default values.
61
62
```typescript { .api }
63
function useQueryState<T>(
64
key: string,
65
options?: UseQueryStateOptions<T>
66
): UseQueryStateReturn<T, undefined>;
67
68
function useQueryState<T>(
69
key: string,
70
options: UseQueryStateOptions<T> & { defaultValue: T }
71
): UseQueryStateReturn<T, T>;
72
73
interface UseQueryStateOptions<T> extends Parser<T>, Options {}
74
75
type UseQueryStateReturn<Parsed, Default> = [
76
Default extends undefined ? Parsed | null : Parsed,
77
(value: Parsed | null | ((old: Parsed | null) => Parsed | null)) => Promise<URLSearchParams>
78
];
79
```
80
81
[Query State Management](./query-states.md)
82
83
### Multiple Query States Management
84
85
Hook for managing multiple related query parameters as a single state object.
86
87
```typescript { .api }
88
function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
89
keyMap: KeyMap,
90
options?: UseQueryStatesOptions
91
): UseQueryStatesReturn<KeyMap>;
92
93
type UseQueryStatesKeysMap<Map = any> = {
94
[Key in keyof Map]: KeyMapValue<Map[Key]>;
95
};
96
97
type UseQueryStatesReturn<T extends UseQueryStatesKeysMap> = [
98
Values<T>,
99
SetValues<T>
100
];
101
```
102
103
[Multiple Query States](./query-states.md)
104
105
### Type-Safe Parsers
106
107
Built-in parsers for common data types with fluent API for configuration and default values.
108
109
```typescript { .api }
110
const parseAsString: ParserBuilder<string>;
111
const parseAsInteger: ParserBuilder<number>;
112
const parseAsHex: ParserBuilder<number>;
113
const parseAsFloat: ParserBuilder<number>;
114
const parseAsBoolean: ParserBuilder<boolean>;
115
const parseAsTimestamp: ParserBuilder<Date>;
116
const parseAsIsoDateTime: ParserBuilder<Date>;
117
118
function parseAsStringEnum<Enum extends string>(validValues: Enum[]): ParserBuilder<Enum>;
119
function parseAsStringLiteral<Literal extends string>(validValues: readonly Literal[]): ParserBuilder<Literal>;
120
function parseAsNumberLiteral<Literal extends number>(validValues: readonly Literal[]): ParserBuilder<Literal>;
121
function parseAsArrayOf<ItemType>(itemParser: Parser<ItemType>, separator?: string): ParserBuilder<ItemType[]>;
122
function parseAsJson<T>(parser?: (value: unknown) => T): ParserBuilder<T>;
123
124
interface ParserBuilder<T> extends Required<Parser<T>> {
125
withDefault(defaultValue: NonNullable<T>): ParserBuilder<T> & { defaultValue: NonNullable<T> };
126
withOptions(options: Options): ParserBuilder<T>;
127
}
128
```
129
130
[Type-Safe Parsers](./parsers.md)
131
132
### Server-Side Cache
133
134
Server-side utilities for accessing and parsing query parameters in React Server Components.
135
136
```typescript { .api }
137
function createSearchParamsCache<Parsers extends Record<string, ParserBuilder<any>>>(
138
parsers: Parsers
139
): {
140
parse(searchParams: SearchParams): ParsedSearchParams;
141
get<Key extends keyof Parsers>(key: Key): ParsedSearchParams[Key];
142
all(): ParsedSearchParams;
143
};
144
145
type SearchParams = Record<string, string | string[] | undefined>;
146
```
147
148
[Server-Side Cache](./server-cache.md)
149
150
### URL Serialization
151
152
Utilities for generating query strings from typed values using parser configuration.
153
154
```typescript { .api }
155
function createSerializer<Parsers extends Record<string, ParserBuilder<any>>>(
156
parsers: Parsers
157
): SerializerFunction<Parsers>;
158
159
interface SerializerFunction<Parsers extends Record<string, ParserBuilder<any>>> {
160
(values: Values<Parsers>): string;
161
(base: string | URLSearchParams | URL, values: Values<Parsers> | null): string;
162
}
163
164
type Values<Parsers extends Record<string, ParserBuilder<any>>> = Partial<{
165
[K in keyof Parsers]?: ExtractParserType<Parsers[K]>;
166
}>;
167
168
type ExtractParserType<Parser> = Parser extends ParserBuilder<any>
169
? ReturnType<Parser['parseServerSide']>
170
: never;
171
```
172
173
[URL Serialization](./serialization.md)
174
175
### Query Update Notifications (Deprecated)
176
177
Deprecated synchronization utility for listening to URL query changes.
178
179
```typescript { .api }
180
/**
181
* @deprecated Since Next.js introduced shallow routing in 14.0.3, this method is no longer needed.
182
* This method will be removed in nuqs@2.0.0.
183
*/
184
function subscribeToQueryUpdates(
185
callback: (args: QueryUpdateNotificationArgs) => void
186
): () => void;
187
188
type QueryUpdateSource = 'internal' | 'external';
189
interface QueryUpdateNotificationArgs {
190
search: URLSearchParams;
191
source: QueryUpdateSource;
192
}
193
```
194
195
### Legacy APIs (Deprecated)
196
197
Deprecated APIs maintained for backward compatibility.
198
199
```typescript { .api }
200
/**
201
* @deprecated renamed to Parser
202
*/
203
type Serializers<T> = Parser<T>;
204
205
/**
206
* @deprecated renamed to ParserBuilder. You should probably use createParser instead.
207
*/
208
type SerializersWithDefaultFactory<T> = ParserBuilder<T>;
209
210
/**
211
* @deprecated use individual parseAsXyz imports instead.
212
*/
213
const queryTypes: {
214
readonly string: ParserBuilder<string>;
215
readonly integer: ParserBuilder<number>;
216
readonly float: ParserBuilder<number>;
217
readonly boolean: ParserBuilder<boolean>;
218
readonly timestamp: ParserBuilder<Date>;
219
readonly isoDateTime: ParserBuilder<Date>;
220
readonly stringEnum: typeof parseAsStringEnum;
221
readonly json: typeof parseAsJson;
222
readonly array: typeof parseAsArrayOf;
223
};
224
225
/**
226
* @deprecated use individual parseAsXyz imports instead
227
*/
228
type QueryTypeMap = typeof queryTypes;
229
```
230
231
## Core Types
232
233
```typescript { .api }
234
interface Parser<T> {
235
/** Convert a query string value into a state value */
236
parse: (value: string) => T | null;
237
/** Render the state value into a query string value */
238
serialize?: (value: T) => string;
239
/** Check if two state values are equal */
240
eq?: (a: T, b: T) => boolean;
241
}
242
243
interface Options<Shallow = unknown> {
244
/** How the query update affects page history (defaults to 'replace') */
245
history?: 'replace' | 'push';
246
/** Scroll to top after a query state update (defaults to false) */
247
scroll?: boolean;
248
/** Shallow mode keeps updates client-side only (defaults to true) */
249
shallow?: Extract<Shallow | boolean, boolean>;
250
/** Maximum time (ms) between URL query string updates (defaults to 50ms) */
251
throttleMs?: number;
252
/** React transition function for observing Server Component loading states */
253
startTransition?: TransitionStartFunction;
254
/** Clear key-value pair from URL when setting state to default value */
255
clearOnDefault?: boolean;
256
}
257
258
type HistoryOptions = 'replace' | 'push';
259
260
type TransitionStartFunction = (callback: () => void) => void;
261
262
type Nullable<T> = {
263
[K in keyof T]: T[K] | null;
264
};
265
```