Skip to content

Commit 517a2b5

Browse files
authored
fix: forward processUrlSearchParams through the debounce queue (#1250)
1 parent a4d3189 commit 517a2b5

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

packages/nuqs/src/lib/queues/debounce.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ export class DebounceController {
8585
push(
8686
update: Omit<UpdateQueuePushArgs, 'timeMs'>,
8787
timeMs: number,
88-
adapter: UpdateQueueAdapterContext
88+
adapter: UpdateQueueAdapterContext,
89+
processUrlSearchParams?: (search: URLSearchParams) => URLSearchParams
8990
): Promise<URLSearchParams> {
9091
if (!Number.isFinite(timeMs)) {
9192
const getSnapshot =
@@ -100,14 +101,16 @@ export class DebounceController {
100101
URLSearchParams
101102
>(update => {
102103
this.throttleQueue.push(update)
103-
return this.throttleQueue.flush(adapter).finally(() => {
104-
const queuedValue = this.queues.get(update.key)?.queuedValue
105-
if (queuedValue === undefined) {
106-
debug('[nuqs dqc] Cleaning up empty queue for `%s`', update.key)
107-
this.queues.delete(update.key)
108-
}
109-
this.queuedQuerySync.emit(update.key)
110-
})
104+
return this.throttleQueue
105+
.flush(adapter, processUrlSearchParams)
106+
.finally(() => {
107+
const queuedValue = this.queues.get(update.key)?.queuedValue
108+
if (queuedValue === undefined) {
109+
debug('[nuqs dqc] Cleaning up empty queue for `%s`', update.key)
110+
this.queues.delete(update.key)
111+
}
112+
this.queuedQuerySync.emit(update.key)
113+
})
111114
})
112115
this.queues.set(key, queue)
113116
}

packages/nuqs/src/useQueryStates.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,28 @@ describe('useQueryStates: process url search params', () => {
935935
expect(onUrlUpdate).toHaveBeenCalledOnce()
936936
expect(onUrlUpdate.mock.calls[0]![0].queryString).toBe('?test=processed')
937937
})
938+
it('should call processUrlSearchParams after a debounced update', async () => {
939+
const onUrlUpdate = vi.fn<OnUrlUpdateFunction>()
940+
const useTestHook = () => useQueryStates({ test: parseAsString })
941+
const { result } = renderHook(useTestHook, {
942+
wrapper: withNuqsTestingAdapter({
943+
processUrlSearchParams: search => {
944+
expect(search.get('test')).toBe('fail')
945+
search.set('test', 'pass')
946+
return search
947+
},
948+
onUrlUpdate
949+
})
950+
})
951+
await act(async () => {
952+
await result.current[1](
953+
{ test: 'fail' },
954+
{ limitUrlUpdates: debounce(50) }
955+
)
956+
})
957+
expect(onUrlUpdate).toHaveBeenCalledOnce()
958+
expect(onUrlUpdate.mock.calls[0]![0].queryString).toBe('?test=pass')
959+
})
938960
})
939961

940962
describe('useQueryStates: edge cases & repros', () => {

packages/nuqs/src/useQueryStates.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
335335
const debouncedPromise = debounceController.push(
336336
update,
337337
timeMs,
338-
adapter
338+
adapter,
339+
processUrlSearchParams
339340
)
340341
if (maxDebounceTime < timeMs) {
341342
// The largest debounce is likely to be the last URL update,

0 commit comments

Comments
 (0)