nuqs
Version:
Type-safe search params state manager for React - Like useState, but stored in the URL query string
79 lines (77 loc) • 2.84 kB
JavaScript
import { debounceController, globalThrottleQueue } from "./debounce-CmqzOOem.js";
import { debug, renderQueryString } from "./context-BWo_DoaC.js";
import { resetQueues } from "./reset-BmRuoRYl.js";
import { markHistoryAsPatched, shouldPatchHistory } from "./patch-history-VL_JehFX.js";
import { startTransition, useCallback, useEffect, useOptimistic } from "react";
import { useRouter, useSearchParams } from "next/navigation.js";
//#region src/adapters/next/impl.app.ts
const NUM_HISTORY_CALLS_PER_UPDATE = 3;
let mutex = 0;
function onPopState() {
mutex = 0;
resetQueues();
}
function onHistoryStateUpdate() {
mutex--;
if (mutex <= 0) {
mutex = 0;
queueMicrotask(resetQueues);
}
}
function patchHistory() {
if (!shouldPatchHistory("next/app")) return;
const originalReplaceState = history.replaceState;
const originalPushState = history.pushState;
history.replaceState = function nuqs_replaceState(state, title, url) {
onHistoryStateUpdate();
return originalReplaceState.call(history, state, title, url);
};
history.pushState = function nuqs_pushState(state, title, url) {
onHistoryStateUpdate();
return originalPushState.call(history, state, title, url);
};
markHistoryAsPatched("next/app");
}
function NavigationSpy() {
useEffect(() => {
patchHistory();
window.addEventListener("popstate", onPopState);
return () => window.removeEventListener("popstate", onPopState);
}, []);
return null;
}
function useNuqsNextAppRouterAdapter() {
const router = useRouter();
const searchParams = useSearchParams();
const [optimisticSearchParams, setOptimisticSearchParams] = useOptimistic(searchParams);
const updateUrl = useCallback((search, options) => {
const queuedThrottledKeys = globalThrottleQueue.reset();
const resetKeysToSync = queuedThrottledKeys.concat(Array.from(debounceController.queuedQuerySync.all.keys()));
startTransition(() => {
if (!options.shallow) {
setOptimisticSearchParams(search);
for (const key of resetKeysToSync) debounceController.queuedQuerySync.emit(key);
}
const url = renderURL(search);
debug("[nuqs next/app] Updating url: %s", url);
const updateMethod = options.history === "push" ? history.pushState : history.replaceState;
mutex = NUM_HISTORY_CALLS_PER_UPDATE;
updateMethod.call(history, null, "", url);
if (options.scroll) window.scrollTo(0, 0);
if (!options.shallow) router.replace(url, { scroll: false });
});
}, []);
return {
searchParams: optimisticSearchParams,
updateUrl,
rateLimitFactor: NUM_HISTORY_CALLS_PER_UPDATE,
autoResetQueueOnUpdate: false
};
}
function renderURL(search) {
const { origin, pathname, hash } = location;
return origin + pathname + renderQueryString(search) + hash;
}
//#endregion
export { NavigationSpy, useNuqsNextAppRouterAdapter };
//# sourceMappingURL=impl.app-H50vLAJE.js.map