0
# Query State Management
1
2
Core hooks for managing URL query parameters as React state, providing type-safe synchronization between component state and URL query strings.
3
4
## Capabilities
5
6
### useQueryState
7
8
Manages a single query parameter as React state with type safety and optional default values.
9
10
```typescript { .api }
11
/**
12
* React state hook synchronized with a URL query string in Next.js
13
* @param key - The URL query string key to bind to
14
* @param options - Parser (defines the state data type), default value and optional history mode
15
*/
16
function useQueryState<T>(
17
key: string,
18
options: UseQueryStateOptions<T> & { defaultValue: T }
19
): UseQueryStateReturn<NonNullable<ReturnType<typeof options.parse>>, typeof options.defaultValue>;
20
21
function useQueryState<T>(
22
key: string,
23
options: UseQueryStateOptions<T>
24
): UseQueryStateReturn<NonNullable<ReturnType<typeof options.parse>>, undefined>;
25
26
function useQueryState(
27
key: string,
28
options: Options & { defaultValue: string }
29
): UseQueryStateReturn<string, typeof options.defaultValue>;
30
31
function useQueryState(
32
key: string,
33
options?: Pick<UseQueryStateOptions<string>, keyof Options>
34
): UseQueryStateReturn<string, undefined>;
35
36
function useQueryState(key: string): UseQueryStateReturn<string, undefined>;
37
38
interface UseQueryStateOptions<T> extends Parser<T>, Options {}
39
40
type UseQueryStateReturn<Parsed, Default> = [
41
Default extends undefined ? Parsed | null : Parsed,
42
<Shallow>(
43
value: Parsed | null | ((old: Default extends Parsed ? Parsed : Parsed | null) => Parsed | null),
44
options?: Options<Shallow>
45
) => Promise<URLSearchParams>
46
];
47
```
48
49
**Usage Examples:**
50
51
```typescript
52
import { useQueryState, parseAsInteger, parseAsBoolean } from "nuqs";
53
54
// String query parameter (default type)
55
const [search, setSearch] = useQueryState('q');
56
// search is string | null, setSearch accepts string | null
57
58
// Integer with default value
59
const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1));
60
// page is number, setPage accepts number | null
61
62
// Boolean with parser options
63
const [active, setActive] = useQueryState('active', {
64
...parseAsBoolean,
65
history: 'push'
66
});
67
68
// Functional updates
69
setPage(oldPage => oldPage + 1);
70
setSearch(null); // Clears the query parameter
71
```
72
73
### useQueryStates
74
75
Manages multiple related query parameters as a single state object with atomic updates.
76
77
```typescript { .api }
78
/**
79
* Synchronise multiple query string arguments to React state in Next.js
80
* @param keyMap - An object describing the keys to synchronise and how to serialise and parse them
81
* @param options - Optional history mode, shallow routing and scroll restoration options
82
*/
83
function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
84
keyMap: KeyMap,
85
options?: UseQueryStatesOptions & { urlKeys?: Partial<Record<keyof KeyMap, string>> }
86
): UseQueryStatesReturn<KeyMap>;
87
88
type UseQueryStatesKeysMap<Map = any> = {
89
[Key in keyof Map]: KeyMapValue<Map[Key]>;
90
};
91
92
type KeyMapValue<Type> = Parser<Type> & Options & { defaultValue?: Type };
93
94
interface UseQueryStatesOptions extends Options {}
95
96
type Values<T extends UseQueryStatesKeysMap> = {
97
[K in keyof T]: T[K]['defaultValue'] extends NonNullable<ReturnType<T[K]['parse']>>
98
? NonNullable<ReturnType<T[K]['parse']>>
99
: ReturnType<T[K]['parse']> | null;
100
};
101
102
type SetValues<T extends UseQueryStatesKeysMap> = (
103
values: Partial<Nullable<Values<T>>> | UpdaterFn<T> | null,
104
options?: Options
105
) => Promise<URLSearchParams>;
106
107
type UpdaterFn<T extends UseQueryStatesKeysMap> = (old: Values<T>) => Partial<Nullable<Values<T>>>;
108
109
type UseQueryStatesReturn<T extends UseQueryStatesKeysMap> = [Values<T>, SetValues<T>];
110
111
type Nullable<T> = { [K in keyof T]: T[K] | null };
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
import { useQueryStates, parseAsInteger, parseAsBoolean, parseAsString } from "nuqs";
118
119
// Define the query state schema
120
const [filters, setFilters] = useQueryStates({
121
search: parseAsString,
122
page: parseAsInteger.withDefault(1),
123
active: parseAsBoolean.withDefault(true),
124
category: parseAsString
125
});
126
127
// Access individual values
128
console.log(filters.search); // string | null
129
console.log(filters.page); // number (always defined due to default)
130
console.log(filters.active); // boolean (always defined due to default)
131
132
// Update multiple values atomically
133
setFilters({
134
search: 'react',
135
page: 1,
136
category: 'frameworks'
137
});
138
139
// Functional updates with access to current state
140
setFilters(current => ({
141
page: current.page + 1,
142
search: current.search?.toUpperCase()
143
}));
144
145
// Clear all managed query parameters
146
setFilters(null);
147
148
// URL key mapping (use different URL keys than state keys)
149
const [state, setState] = useQueryStates({
150
searchTerm: parseAsString,
151
pageNumber: parseAsInteger.withDefault(1)
152
}, {
153
urlKeys: {
154
searchTerm: 'q',
155
pageNumber: 'p'
156
}
157
});
158
```
159
160
### Options Configuration
161
162
Both hooks support comprehensive configuration options:
163
164
```typescript { .api }
165
interface Options<Shallow = unknown> {
166
/** How the query update affects page history (defaults to 'replace') */
167
history?: HistoryOptions;
168
/** Scroll to top after a query state update (defaults to false) */
169
scroll?: boolean;
170
/** Shallow mode keeps query states update client-side only (defaults to true) */
171
shallow?: Extract<Shallow | boolean, boolean>;
172
/** Maximum time (ms) between URL query string updates (defaults to 50ms) */
173
throttleMs?: number;
174
/** Clear key-value pair from URL when setting state to default value */
175
clearOnDefault?: boolean;
176
/** React transition function for observing Server Component loading states */
177
startTransition?: TransitionStartFunction;
178
}
179
180
type HistoryOptions = 'replace' | 'push';
181
type TransitionStartFunction = (callback: () => void) => void;
182
```
183
184
**Configuration Examples:**
185
186
```typescript
187
// Hook-level options
188
const [search, setSearch] = useQueryState('q', {
189
history: 'push', // Use browser back/forward
190
scroll: false, // Don't scroll on updates
191
throttleMs: 100, // Throttle URL updates
192
clearOnDefault: true // Remove from URL when set to default
193
});
194
195
// Call-level options (override hook options)
196
setSearch('react', {
197
history: 'replace',
198
shallow: false
199
});
200
201
// React 18 transitions for server updates
202
const [isPending, startTransition] = useTransition();
203
const [data, setData] = useQueryState('data', {
204
shallow: false,
205
startTransition
206
});
207
```
208
209
### Error Handling
210
211
The hooks handle various error conditions gracefully:
212
213
- Invalid query string values are parsed as `null`
214
- Parser errors return `null` instead of throwing
215
- URL updates are throttled to prevent browser rate limiting
216
- Multiple hook instances are automatically synchronized