Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Abstract reading from location.search in adapters interface #800

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/nuqs/src/adapters/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export type UseAdapterHook = () => AdapterInterface
export type AdapterInterface = {
searchParams: URLSearchParams
updateUrl: UpdateUrlFunction
getSearchParamsSnapshot?: () => URLSearchParams
rateLimitFactor?: number
}
3 changes: 3 additions & 0 deletions packages/nuqs/src/adapters/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export function NuqsTestingAdapter({
options
})
},
getSearchParamsSnapshot() {
return new URLSearchParams(props.searchParams)
},
rateLimitFactor: props.rateLimitFactor ?? 0
})
return createElement(
Expand Down
33 changes: 22 additions & 11 deletions packages/nuqs/src/update-queue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UpdateUrlFunction } from './adapters/defs'
import type { AdapterInterface } from './adapters/defs'
import { debug } from './debug'
import type { Options } from './defs'
import { error } from './errors'
Expand Down Expand Up @@ -76,15 +76,19 @@ export function enqueueQueryStringUpdate<Value>(
*
* @returns a Promise to the URLSearchParams that have been applied.
*/
export function scheduleFlushToURL(
updateUrl: UpdateUrlFunction,
rateLimitFactor: number
) {
export function scheduleFlushToURL({
getSearchParamsSnapshot = () => new URLSearchParams(location.search),
updateUrl,
rateLimitFactor = 1
}: Pick<
AdapterInterface,
'updateUrl' | 'getSearchParamsSnapshot' | 'rateLimitFactor'
>) {
if (flushPromiseCache === null) {
flushPromiseCache = new Promise<URLSearchParams>((resolve, reject) => {
if (!Number.isFinite(queueOptions.throttleMs)) {
debug('[nuqs queue] Skipping flush due to throttleMs=Infinity')
resolve(new URLSearchParams(location.search))
resolve(getSearchParamsSnapshot())
// Let the promise be returned before clearing the cached value
setTimeout(() => {
flushPromiseCache = null
Expand All @@ -93,7 +97,10 @@ export function scheduleFlushToURL(
}
function flushNow() {
lastFlushTimestamp = performance.now()
const [search, error] = flushUpdateQueue(updateUrl)
const [search, error] = flushUpdateQueue({
updateUrl,
getSearchParamsSnapshot
})
if (error === null) {
resolve(search)
} else {
Expand Down Expand Up @@ -129,10 +136,14 @@ export function scheduleFlushToURL(
return flushPromiseCache
}

function flushUpdateQueue(
updateUrl: UpdateUrlFunction
): [URLSearchParams, null | unknown] {
const search = new URLSearchParams(location.search)
function flushUpdateQueue({
updateUrl,
getSearchParamsSnapshot
}: Pick<Required<AdapterInterface>, 'updateUrl' | 'getSearchParamsSnapshot'>): [
URLSearchParams,
null | unknown
] {
const search = getSearchParamsSnapshot()
if (updateQueue.size === 0) {
return [search, null]
}
Expand Down
21 changes: 4 additions & 17 deletions packages/nuqs/src/useQueryState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,8 @@ export function useQueryState<T = string>(
defaultValue: undefined
}
) {
// Not reactive, but available on the server and on page load
const {
searchParams: initialSearchParams,
updateUrl,
rateLimitFactor = 1
} = useAdapter()
const adapter = useAdapter()
const initialSearchParams = adapter.searchParams
const queryRef = useRef<string | null>(initialSearchParams?.get(key) ?? null)
const [internalState, setInternalState] = useState<T | null>(() => {
const queuedQuery = getQueuedValue(key)
Expand Down Expand Up @@ -302,18 +298,9 @@ export function useQueryState<T = string>(
})
// Sync all hooks state (including this one)
emitter.emit(key, { state: newValue, query: queryRef.current })
return scheduleFlushToURL(updateUrl, rateLimitFactor)
return scheduleFlushToURL(adapter)
},
[
key,
history,
shallow,
scroll,
throttleMs,
startTransition,
updateUrl,
rateLimitFactor
]
[key, history, shallow, scroll, throttleMs, startTransition, adapter]
)
return [internalState ?? defaultValue ?? null, update]
}
Expand Down
12 changes: 4 additions & 8 deletions packages/nuqs/src/useQueryStates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,8 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
),
[stateKeys, urlKeys]
)
const {
searchParams: initialSearchParams,
updateUrl,
rateLimitFactor = 1
} = useAdapter()
const adapter = useAdapter()
const initialSearchParams = adapter.searchParams
const queryRef = useRef<Record<string, string | null>>({})
// Initialise the queryRef with the initial values
if (Object.keys(queryRef.current).length !== Object.keys(keyMap).length) {
Expand Down Expand Up @@ -243,7 +240,7 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
query: queryRef.current[urlKey] ?? null
})
}
return scheduleFlushToURL(updateUrl, rateLimitFactor)
return scheduleFlushToURL(adapter)
},
[
keyMap,
Expand All @@ -253,8 +250,7 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
throttleMs,
startTransition,
resolvedUrlKeys,
updateUrl,
rateLimitFactor,
adapter,
defaultValues
]
)
Expand Down
Loading