use-query-params
Version:
React Hook for managing state in URL query parameters with easy serialization.
57 lines (49 loc) • 1.77 kB
text/typescript
import { EncodedQuery } from 'serialize-query-params';
import shallowEqual from './shallowEqual';
import { deserializeUrlNameMap } from './urlName';
let cachedSearchString: string | undefined;
let cachedUrlNameMapString: string | undefined;
let cachedSearchStringToObjectFn:
| ((searchString: string) => EncodedQuery)
| undefined;
let cachedParsedQuery: EncodedQuery = {};
/**
* cached conversion of ?foo=1&bar=2 to { foo: '1', bar: '2' }
*/
export const memoSearchStringToObject = (
searchStringToObject: (searchString: string) => EncodedQuery,
searchString?: string | undefined,
/** optionally provide a mapping string to handle renames via `urlName`
* mapping are separated by \n and mappings are urlName\0paramName
*/
urlNameMapStr?: string | undefined
) => {
// if we have a cached version, just return it
if (
cachedSearchString === searchString &&
cachedSearchStringToObjectFn === searchStringToObject &&
cachedUrlNameMapString === urlNameMapStr
) {
return cachedParsedQuery;
}
cachedSearchString = searchString;
cachedSearchStringToObjectFn = searchStringToObject;
const newParsedQuery = searchStringToObject(searchString ?? '');
cachedUrlNameMapString = urlNameMapStr;
const urlNameMap = deserializeUrlNameMap(urlNameMapStr);
// keep old values for keys if they are the same
for (let [key, value] of Object.entries(newParsedQuery)) {
// handle url name mapping
if (urlNameMap?.[key]) {
delete newParsedQuery[key];
key = urlNameMap[key];
newParsedQuery[key] = value;
}
const oldValue = cachedParsedQuery[key];
if (shallowEqual(value, oldValue)) {
newParsedQuery[key] = oldValue;
}
}
cachedParsedQuery = newParsedQuery;
return newParsedQuery;
};