UNPKG

@thibault.sh/hooks

Version:

A comprehensive collection of React hooks for browser storage, UI interactions, and more

1 lines 4.49 kB
{"version":3,"sources":["../src/hooks/useQueryParamsState.ts"],"names":["useQueryParamsState","key","initialValue","options","serialize","deserialize","readValue","useCallback","item","error","value","setValue","useState","updateValue","newValue","valueToStore","params","newUrl","useEffect","handlePopState"],"mappings":"wCAWO,SAASA,CACdC,CAAAA,CAAAA,CACAC,EACAC,CAGI,CAAA,GACuC,CAC3C,GAAM,CAAE,SAAAC,CAAAA,CAAAA,CAAY,KAAK,SAAW,CAAA,WAAA,CAAAC,EAAc,IAAK,CAAA,KAAM,EAAIF,CAG3DG,CAAAA,CAAAA,CAAYC,kBAAY,IAAS,CACrC,GAAI,OAAO,MAAA,EAAW,YACpB,OAAOL,CAAAA,CAGT,GAAI,CAEF,IAAMM,EADS,IAAI,eAAA,CAAgB,OAAO,QAAS,CAAA,MAAM,EACrC,GAAIP,CAAAA,CAAG,EAC3B,OAAOO,CAAAA,CAAOH,EAAYG,CAAI,CAAA,CAAIN,CACpC,CAASO,MAAAA,CAAAA,CAAO,CACd,OAAQ,OAAA,CAAA,IAAA,CAAK,kCAAkCR,CAAG,CAAA,EAAA,CAAA,CAAMQ,CAAK,CACtDP,CAAAA,CACT,CACF,CAAG,CAAA,CAACD,EAAKC,CAAcG,CAAAA,CAAW,CAAC,CAE7B,CAAA,CAACK,EAAOC,CAAQ,CAAA,CAAIC,eAAYN,CAAS,CAAA,CAGzCO,EAAcN,iBACjBO,CAAAA,CAAAA,EAAkC,CACjC,GAAI,CAEF,IAAMC,CAAeD,CAAAA,CAAAA,YAAoB,SAAWA,CAASJ,CAAAA,CAAK,EAAII,CAMtE,CAAA,GAHAH,EAASI,CAAY,CAAA,CAGjB,OAAO,MAAW,EAAA,WAAA,CAAa,CACjC,IAAMC,CAAAA,CAAS,IAAI,eAAgB,CAAA,MAAA,CAAO,SAAS,MAAM,CAAA,CACzDA,EAAO,GAAIf,CAAAA,CAAAA,CAAKG,EAAUW,CAAY,CAAC,EAGvC,IAAME,CAAAA,CAAS,GAAG,MAAO,CAAA,QAAA,CAAS,QAAQ,CAAID,CAAAA,EAAAA,CAAAA,CAAO,UAAU,CAAA,CAAA,CAC/D,OAAO,OAAQ,CAAA,SAAA,CAAU,EAAI,CAAA,EAAA,CAAIC,CAAM,EACzC,CACF,OAASR,CAAO,CAAA,CACd,QAAQ,IAAK,CAAA,CAAA,+BAAA,EAAkCR,CAAG,CAAMQ,EAAAA,CAAAA,CAAAA,CAAK,EAC/D,CACF,CAAA,CACA,CAACR,CAAKG,CAAAA,CAAAA,CAAWM,CAAK,CACxB,CAAA,CAGA,OAAAQ,eAAU,CAAA,IAAM,CACd,IAAMC,CAAAA,CAAiB,IAAM,CAC3BR,CAAAA,CAASL,GAAW,EACtB,EAEA,OAAO,MAAA,CAAA,gBAAA,CAAiB,WAAYa,CAAc,CAAA,CAC3C,IAAM,MAAO,CAAA,mBAAA,CAAoB,WAAYA,CAAc,CACpE,EAAG,CAACb,CAAS,CAAC,CAEP,CAAA,CAACI,CAAOG,CAAAA,CAAW,CAC5B","file":"useQueryParamsState.cjs","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\n\n/**\n * Hook for managing state persisted in URL query parameters\n * @param key - The query parameter key\n * @param initialValue - The initial value to use if the parameter doesn't exist\n * @param options - Configuration options\n * @param options.serialize - Function to convert value to string (default: JSON.stringify)\n * @param options.deserialize - Function to parse string back to value (default: JSON.parse)\n * @returns A tuple containing the current value and a setter function\n */\nexport function useQueryParamsState<T>(\n key: string,\n initialValue: T,\n options: {\n serialize?: (value: T) => string;\n deserialize?: (value: string) => T;\n } = {}\n): [T, (value: T | ((val: T) => T)) => void] {\n const { serialize = JSON.stringify, deserialize = JSON.parse } = options;\n\n // Read value from URL\n const readValue = useCallback((): T => {\n if (typeof window === \"undefined\") {\n return initialValue;\n }\n\n try {\n const params = new URLSearchParams(window.location.search);\n const item = params.get(key);\n return item ? deserialize(item) : initialValue;\n } catch (error) {\n console.warn(`Error reading query parameter \"${key}\":`, error);\n return initialValue;\n }\n }, [key, initialValue, deserialize]);\n\n const [value, setValue] = useState<T>(readValue);\n\n // Update state and URL when value changes\n const updateValue = useCallback(\n (newValue: T | ((val: T) => T)) => {\n try {\n // Allow value to be a function so we have same API as useState\n const valueToStore = newValue instanceof Function ? newValue(value) : newValue;\n\n // Update state\n setValue(valueToStore);\n\n // Update URL\n if (typeof window !== \"undefined\") {\n const params = new URLSearchParams(window.location.search);\n params.set(key, serialize(valueToStore));\n\n // Update URL without causing page reload\n const newUrl = `${window.location.pathname}?${params.toString()}`;\n window.history.pushState({}, \"\", newUrl);\n }\n } catch (error) {\n console.warn(`Error setting query parameter \"${key}\":`, error);\n }\n },\n [key, serialize, value]\n );\n\n // Sync with URL changes (e.g., browser back/forward)\n useEffect(() => {\n const handlePopState = () => {\n setValue(readValue());\n };\n\n window.addEventListener(\"popstate\", handlePopState);\n return () => window.removeEventListener(\"popstate\", handlePopState);\n }, [readValue]);\n\n return [value, updateValue];\n}\n"]}