UNPKG

nuqs

Version:

Type-safe search params state manager for React - Like useState, but stored in the URL query string

75 lines (72 loc) 3.18 kB
'use client'; import { createEmitter } from "../debounce-CmqzOOem.js"; import { createAdapterProvider, debug, renderQueryString } from "../context-BWo_DoaC.js"; import { applyChange, filterSearchParams } from "../key-isolation-CKEBJ11E.js"; import "../reset-BmRuoRYl.js"; import { historyUpdateMarker, patchHistory } from "../patch-history-VL_JehFX.js"; import { createContext, createElement, useContext, useEffect, useMemo, useState } from "react"; //#region src/adapters/react.ts const emitter = createEmitter(); function generateUpdateUrlFn(fullPageNavigationOnShallowFalseUpdates) { return function updateUrl(search, options) { const url = new URL(location.href); url.search = renderQueryString(search); debug("[nuqs react] Updating url: %s", url); if (fullPageNavigationOnShallowFalseUpdates && options.shallow === false) { const method = options.history === "push" ? location.assign : location.replace; method.call(location, url); } else { const method = options.history === "push" ? history.pushState : history.replaceState; method.call(history, history.state, historyUpdateMarker, url); } emitter.emit("update", search); if (options.scroll === true) window.scrollTo({ top: 0 }); }; } const NuqsReactAdapterContext = createContext({ fullPageNavigationOnShallowFalseUpdates: false }); function useNuqsReactAdapter(watchKeys) { const { fullPageNavigationOnShallowFalseUpdates } = useContext(NuqsReactAdapterContext); const [searchParams, setSearchParams] = useState(() => { if (typeof location === "undefined") return new URLSearchParams(); return filterSearchParams(new URLSearchParams(location.search), watchKeys, false); }); useEffect(() => { const onPopState = () => { setSearchParams(applyChange(new URLSearchParams(location.search), watchKeys, false)); }; const onEmitterUpdate = (search) => { setSearchParams(applyChange(search, watchKeys, true)); }; emitter.on("update", onEmitterUpdate); window.addEventListener("popstate", onPopState); return () => { emitter.off("update", onEmitterUpdate); window.removeEventListener("popstate", onPopState); }; }, [watchKeys.join("&")]); const updateUrl = useMemo(() => generateUpdateUrlFn(fullPageNavigationOnShallowFalseUpdates), [fullPageNavigationOnShallowFalseUpdates]); return { searchParams, updateUrl }; } const NuqsReactAdapter = createAdapterProvider(useNuqsReactAdapter); function NuqsAdapter({ children, fullPageNavigationOnShallowFalseUpdates = false,...adapterProps }) { return createElement(NuqsReactAdapterContext.Provider, { value: { fullPageNavigationOnShallowFalseUpdates } }, createElement(NuqsReactAdapter, { ...adapterProps, children })); } /** * Opt-in to syncing shallow updates of the URL with the useOptimisticSearchParams hook. * * By default, the useOptimisticSearchParams hook will only react to internal nuqs updates. * If third party code updates the History API directly, use this function to * enable useOptimisticSearchParams to react to those changes. */ function enableHistorySync() { patchHistory(emitter, "react"); } //#endregion export { NuqsAdapter, enableHistorySync }; //# sourceMappingURL=react.js.map