Socket
Socket
Sign inDemoInstall

use-query-params

Package Overview
Dependencies
10
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.6.0 to 1.0.0

esm/helpers.d.ts

5

esm/index.d.ts

@@ -5,5 +5,4 @@ export * from 'serialize-query-params';

export { useQueryParams } from './useQueryParams';
export { withQueryParams, InjectedQueryProps } from './withQueryParams';
export { withQueryParams, withQueryParamsMapped, InjectedQueryProps, } from './withQueryParams';
export { QueryParams, QueryParamsProps, QueryRenderProps } from './QueryParams';
export { updateUrlQuery } from './updateUrlQuery';
export { QueryParamProvider, QueryParamContext, QueryParamContextValue, } from './QueryParamProvider';
export { QueryParamProvider } from './QueryParamProvider';
export * from 'serialize-query-params';
export { useQueryParam } from './useQueryParam';
export { useQueryParams } from './useQueryParams';
export { withQueryParams } from './withQueryParams';
export { withQueryParams, withQueryParamsMapped, } from './withQueryParams';
export { QueryParams } from './QueryParams';
export { updateUrlQuery } from './updateUrlQuery';
export { QueryParamProvider, QueryParamContext, } from './QueryParamProvider';
export { QueryParamProvider } from './QueryParamProvider';

16

esm/QueryParamProvider.d.ts
import * as React from 'react';
import { PushReplaceHistory } from './types';
import { HistoryLocation, PushReplaceHistory } from './types';
/**

@@ -14,10 +14,6 @@ * Subset of a @reach/router history object. We only

/**
* Shape of the QueryParamContext, needed to update the URL
* and know its current state.
* Helper to produce the context value falling back to
* window history and location if not provided.
*/
export interface QueryParamContextValue {
history: PushReplaceHistory;
location: Location;
}
export declare const QueryParamContext: React.Context<QueryParamContextValue>;
export declare function getLocationProps({ history, location, }?: Partial<HistoryLocation>): HistoryLocation;
/**

@@ -27,3 +23,3 @@ * Props for the Provider component, used to hook the active routing

*/
interface Props {
interface QueryParamProviderProps {
/** Main app goes here */

@@ -47,3 +43,3 @@ children: React.ReactNode;

*/
export declare function QueryParamProvider({ children, ReactRouterRoute, reachHistory, history, location, }: Props): JSX.Element;
export declare function QueryParamProvider({ children, ReactRouterRoute, reachHistory, history, location, }: QueryParamProviderProps): JSX.Element;
export default QueryParamProvider;

@@ -13,2 +13,6 @@ var __assign = (this && this.__assign) || function () {

import * as React from 'react';
import { LocationProvider } from './LocationProvider';
// we use a lazy caching solution to prevent #46 from happening
var cachedWindowHistory;
var cachedAdaptedWindowHistory;
/**

@@ -21,3 +25,6 @@ * Adapts standard DOM window history to work with our

function adaptWindowHistory(history) {
return {
if (history === cachedWindowHistory && cachedAdaptedWindowHistory != null) {
return cachedAdaptedWindowHistory;
}
var adaptedWindowHistory = {
replace: function (location) {

@@ -30,3 +37,9 @@ history.replaceState(location.state, '', location.protocol + "//" + location.host + location.pathname + location.search);

};
cachedWindowHistory = history;
cachedAdaptedWindowHistory = adaptedWindowHistory;
return adaptedWindowHistory;
}
// we use a lazy caching solution to prevent #46 from happening
var cachedReachHistory;
var cachedAdaptedReachHistory;
/**

@@ -39,3 +52,6 @@ * Adapts @reach/router history to work with our

function adaptReachHistory(history) {
return {
if (history === cachedReachHistory && cachedAdaptedReachHistory != null) {
return cachedAdaptedReachHistory;
}
var adaptedReachHistory = {
replace: function (location) {

@@ -48,2 +64,5 @@ history.navigate(location.protocol + "//" + location.host + location.pathname + location.search, { replace: true });

};
cachedReachHistory = history;
cachedAdaptedReachHistory = adaptedReachHistory;
return adaptedReachHistory;
}

@@ -54,17 +73,18 @@ /**

*/
function getContextValue(contextValue) {
if (contextValue === void 0) { contextValue = {}; }
var value = __assign({}, contextValue);
export function getLocationProps(_a) {
var _b = _a === void 0 ? {} : _a, history = _b.history, location = _b.location;
var hasWindow = typeof window !== 'undefined';
if (hasWindow) {
if (!value.history) {
value.history = adaptWindowHistory(window.history);
if (!history) {
history = adaptWindowHistory(window.history);
}
if (!value.location) {
value.location = window.location;
if (!location) {
location = window.location;
}
}
return value;
if (!location) {
throw new Error("\n Could not read the location. Is the router wired up correctly?\n ");
}
return { history: history, location: location };
}
export var QueryParamContext = React.createContext(getContextValue());
/**

@@ -79,3 +99,3 @@ * Context provider for query params to have access to the

return (React.createElement(ReactRouterRoute, null, function (routeProps) {
return (React.createElement(QueryParamContext.Provider, { value: getContextValue(routeProps) }, children));
return (React.createElement(LocationProvider, __assign({}, getLocationProps(routeProps)), children));
}));

@@ -85,10 +105,10 @@ }

if (reachHistory) {
return (React.createElement(QueryParamContext.Provider, { value: getContextValue({
history: adaptReachHistory(reachHistory),
location: location,
}) }, children));
return (React.createElement(LocationProvider, __assign({}, getLocationProps({
history: adaptReachHistory(reachHistory),
location: location,
})), children));
}
// neither reach nor react-router, so allow manual overrides
return (React.createElement(QueryParamContext.Provider, { value: getContextValue({ history: history, location: location }) }, children));
return (React.createElement(LocationProvider, __assign({}, getLocationProps({ history: history, location: location })), children));
}
export default QueryParamProvider;

@@ -18,3 +18,2 @@ import { QueryParamConfigMap, DecodedValueMap } from 'serialize-query-params';

replace: (location: Location) => void;
location?: Location;
}

@@ -25,1 +24,10 @@ /**

export declare type SetQuery<QPCMap extends QueryParamConfigMap> = (changes: Partial<DecodedValueMap<QPCMap>>, updateType?: UrlUpdateType) => void;
export interface HistoryLocation {
/**
* History that meets the { replace, push } interface.
* May be missing when run server-side.
*/
history?: PushReplaceHistory;
/** The location object */
location: Location;
}

@@ -1,10 +0,14 @@

import { EncodedQueryWithNulls } from 'serialize-query-params';
import { EncodedQuery } from 'serialize-query-params';
import { PushReplaceHistory, UrlUpdateType } from './types';
/**
* Updates the URL to match the specified query changes.
* Creates a new location object containing the specified query changes.
* If replaceIn or pushIn are used as the updateType, then parameters
* not specified in queryReplacements are retained. If replace or push
* are used, only the values in queryReplacements will be available.
* The default is pushIn.
*/
export declare function updateUrlQuery(queryReplacements: EncodedQueryWithNulls, location: Location, history: PushReplaceHistory, updateType?: UrlUpdateType): void;
export default updateUrlQuery;
export declare function createLocationWithChanges(queryReplacements: EncodedQuery, location: Location, updateType?: UrlUpdateType): Location;
/**
* Updates the URL to the new location.
*/
export declare function updateUrlQuery(history: PushReplaceHistory, location: Location, updateType?: UrlUpdateType): void;
import { updateLocation, updateInLocation, } from 'serialize-query-params';
/**
* Updates the URL to match the specified query changes.
* Creates a new location object containing the specified query changes.
* If replaceIn or pushIn are used as the updateType, then parameters
* not specified in queryReplacements are retained. If replace or push
* are used, only the values in queryReplacements will be available.
* The default is pushIn.
*/
export function updateUrlQuery(queryReplacements, location, history, updateType) {
if (updateType === void 0) { updateType = 'replaceIn'; }
export function createLocationWithChanges(queryReplacements, location, updateType) {
if (updateType === void 0) { updateType = 'pushIn'; }
switch (updateType) {
case 'replace':
case 'push':
return updateLocation(queryReplacements, location);
case 'replaceIn':
history.replace(updateInLocation(queryReplacements, location));
break;
case 'pushIn':
history.push(updateInLocation(queryReplacements, location));
default:
return updateInLocation(queryReplacements, location);
}
}
/**
* Updates the URL to the new location.
*/
export function updateUrlQuery(history, location, updateType) {
if (updateType === void 0) { updateType = 'pushIn'; }
switch (updateType) {
case 'pushIn':
case 'push':
history.push(location);
break;
case 'replaceIn':
case 'replace':
history.replace(updateLocation(queryReplacements, location));
default:
history.replace(location);
break;
case 'push':
history.push(updateLocation(queryReplacements, location));
break;
default:
}
}
export default updateUrlQuery;

@@ -1,2 +0,2 @@

import { EncodedQueryWithNulls, QueryParamConfig } from 'serialize-query-params';
import { QueryParamConfig } from 'serialize-query-params';
/**

@@ -8,6 +8,6 @@ * Given a query param name and query parameter configuration ({ encode, decode })

* is one of 'replace' | 'replaceIn' | 'push' | 'pushIn', defaulting to
* 'replaceIn'.
* 'pushIn'.
*
* You may optionally pass in a rawQuery object, otherwise the query is derived
* from the location available in the QueryParamContext.
* from the location available in the context.
*

@@ -17,2 +17,2 @@ * D = decoded type

*/
export declare const useQueryParam: <D, D2 = D>(name: string, paramConfig?: QueryParamConfig<D, D2>, rawQuery?: EncodedQueryWithNulls | undefined) => [D2 | undefined, (newValue: D, updateType?: "replace" | "push" | "replaceIn" | "pushIn" | undefined) => void];
export declare const useQueryParam: <D, D2 = D>(name: string, paramConfig?: QueryParamConfig<D, D2>) => [D2 | undefined, (newValue: D, updateType?: "replace" | "push" | "replaceIn" | "pushIn" | undefined) => void];
import * as React from 'react';
import { parse as parseQueryString, parseUrl as parseQueryURL, stringify, StringParam, } from 'serialize-query-params';
import { QueryParamContext } from './QueryParamProvider';
import { updateUrlQuery } from './updateUrlQuery';
import { StringParam } from 'serialize-query-params';
import { getSSRSafeSearchString, usePreviousIfShallowEqual } from './helpers';
import { useLocationContext } from './LocationContext';
import { sharedMemoizedQueryParser } from './memoizedQueryParser';
/**

@@ -11,6 +12,6 @@ * Given a query param name and query parameter configuration ({ encode, decode })

* is one of 'replace' | 'replaceIn' | 'push' | 'pushIn', defaulting to
* 'replaceIn'.
* 'pushIn'.
*
* You may optionally pass in a rawQuery object, otherwise the query is derived
* from the location available in the QueryParamContext.
* from the location available in the context.
*

@@ -20,66 +21,23 @@ * D = decoded type

*/
export var useQueryParam = function (name, paramConfig, rawQuery) {
var _a;
export var useQueryParam = function (name, paramConfig) {
if (paramConfig === void 0) { paramConfig = StringParam; }
var _b = React.useContext(QueryParamContext), history = _b.history, location = _b.location;
// ref with current version history object (see #46)
var refHistory = React.useRef(history);
React.useEffect(function () {
refHistory.current = history;
}, [history]);
// ref with current version location object (see #46)
var refLocation = React.useRef(location);
React.useEffect(function () {
refLocation.current = location;
}, [location]);
var _a = useLocationContext(), location = _a[0], setLocation = _a[1];
// create the setter, memoizing via useCallback
var setValue = React.useCallback(function (newValue, updateType) {
var _a;
var newEncodedValue = paramConfig.encode(newValue);
setLocation((_a = {}, _a[name] = newEncodedValue, _a), updateType);
}, [paramConfig, name, setLocation]);
// read in the raw query
if (!rawQuery) {
var locationIsObject_1 = typeof location === 'object';
var windowIsDefined_1 = typeof window !== 'undefined';
rawQuery = React.useMemo(function () {
var pathname = {};
// handle checking SSR (#13)
if (locationIsObject_1) {
// in browser
if (windowIsDefined_1) {
pathname = parseQueryString(location.search);
}
else {
// not in browser
var url = location.pathname;
if (location.search) {
url += location.search;
}
pathname = parseQueryURL(url).query;
}
}
return pathname || {};
}, [location.search, location.pathname, locationIsObject_1, windowIsDefined_1]);
}
// read in the encoded string value
var encodedValue = rawQuery[name];
// note that we use the stringified encoded value since the encoded
// value may be an array that is recreated if a different query param
// changes. It is sufficient to use this instead of encodedValue in
// the useMemo dependency array since it will change any time the actual
// meaningful value of encodedValue changes.
var arraySafeEncodedValue = encodedValue instanceof Array
? stringify((_a = {}, _a[name] = encodedValue, _a))
: encodedValue;
var parsedQuery = sharedMemoizedQueryParser(getSSRSafeSearchString(location));
// read in the encoded string value (we have to use previous if available because
// sometimes the query string changes so we get a new parsedQuery but this value
// didn't change, so we should avoid generating a new array or whatever value)
var encodedValue = usePreviousIfShallowEqual(parsedQuery[name]);
// decode if the encoded value has changed, otherwise
// re-use memoized value
var decodedValue = React.useMemo(function () {
if (encodedValue == null) {
return undefined;
}
return paramConfig.decode(encodedValue);
}, [arraySafeEncodedValue, paramConfig]); // eslint-disable-line react-hooks/exhaustive-deps
// create the setter, memoizing via useCallback
var setValue = React.useCallback(function (newValue, updateType) {
var _a;
var newEncodedValue = paramConfig.encode(newValue);
updateUrlQuery((_a = {}, _a[name] = newEncodedValue, _a), refHistory.current.location || refLocation.current, // see #46 for why we use a ref here
refHistory.current, updateType);
}, [paramConfig, name]);
}, [encodedValue, paramConfig]);
return [decodedValue, setValue];
};
import * as React from 'react';
import { parse as parseQueryString, encodeQueryParams, } from 'serialize-query-params';
import { useQueryParam } from './useQueryParam';
import updateUrlQuery from './updateUrlQuery';
import { QueryParamContext } from './QueryParamProvider';
// from https://usehooks.com/usePrevious/
function usePrevious(value) {
var ref = React.useRef(value);
React.useEffect(function () {
ref.current = value;
}, [value]);
return ref.current;
}
// from https://github.com/lodash/lodash/issues/2340#issuecomment-360325395
function isShallowEqual(objA, objB) {
for (var key in objA)
if (!(key in objB) || objA[key] !== objB[key])
return false;
for (var key in objB)
if (!(key in objA) || objA[key] !== objB[key])
return false;
return true;
}
import { encodeQueryParams, } from 'serialize-query-params';
import { getSSRSafeSearchString, usePreviousIfShallowEqual } from './helpers';
import { useLocationContext } from './LocationContext';
import { sharedMemoizedQueryParser } from './memoizedQueryParser';
import shallowEqual from './shallowEqual';
/**

@@ -29,52 +12,46 @@ * Given a query parameter configuration (mapping query param name to { encode, decode }),

export var useQueryParams = function (paramConfigMap) {
var _a = React.useContext(QueryParamContext), history = _a.history, location = _a.location;
var locationIsObject = typeof location === 'object';
var _a = useLocationContext(), location = _a[0], setLocation = _a[1];
var decodedValueCacheRef = React.useRef({});
// memoize paramConfigMap to make the API nicer for consumers.
// otherwise we'd have to useQueryParams(useMemo(() => { foo: NumberParam }, []))
var prevParamConfigMap = usePrevious(paramConfigMap);
var hasNewParamConfig = isShallowEqual(prevParamConfigMap, paramConfigMap);
// prettier-ignore
var memoParamConfigMap = React.useMemo(function () { return paramConfigMap; }, [
hasNewParamConfig,
]);
paramConfigMap = memoParamConfigMap;
// ref with current version history object (see #46)
var refHistory = React.useRef(history);
React.useEffect(function () {
refHistory.current = history;
}, [history]);
// ref with current version location object (see #46)
var refLocation = React.useRef(location);
React.useEffect(function () {
refLocation.current = location;
}, [location]);
var search = locationIsObject ? location.search : '';
paramConfigMap = usePreviousIfShallowEqual(paramConfigMap);
// create a setter for updating multiple query params at once
var setQuery = React.useCallback(function (changes, updateType) {
// encode as strings for the URL
var encodedChanges = encodeQueryParams(paramConfigMap, changes);
// update the URL
setLocation(encodedChanges, updateType);
}, [paramConfigMap, setLocation]);
// read in the raw query
var rawQuery = React.useMemo(function () { return parseQueryString(search) || {}; }, [
search,
]);
// parse each parameter via useQueryParam
// we reuse the logic to not recreate objects
var paramNames = Object.keys(paramConfigMap);
var paramValues = paramNames.map(function (paramName) {
return useQueryParam(paramName, paramConfigMap[paramName], rawQuery)[0];
});
// we use a memo here to prevent recreating the containing decodedValues object
// which would break === comparisons even if no values changed.
var parsedQuery = sharedMemoizedQueryParser(getSSRSafeSearchString(location));
// decode all the values if we have changes
var decodedValues = React.useMemo(function () {
// iterate over the decoded values and build an object
var decodedValueCache = decodedValueCacheRef.current;
// we are decoding since the parsed query changed or the param config map has changed.
// recompute new values but only for those that changed
var paramNames = Object.keys(paramConfigMap);
var decodedValues = {};
for (var i = 0; i < paramNames.length; ++i) {
decodedValues[paramNames[i]] = paramValues[i];
for (var _i = 0, paramNames_1 = paramNames; _i < paramNames_1.length; _i++) {
var paramName = paramNames_1[_i];
var paramConfig = paramConfigMap[paramName];
var encodedValue = parsedQuery[paramName];
var decodedValue = void 0;
// re-use cached decoded value if we can, otherwise generate new
var cacheEntry = decodedValueCache[paramName];
if (cacheEntry != undefined &&
shallowEqual(cacheEntry.encodedValue, encodedValue)) {
decodedValue = cacheEntry.decodedValue;
}
else {
if (cacheEntry == null) {
decodedValueCache[paramName] = {};
}
decodedValue = paramConfig.decode(encodedValue);
decodedValueCache[paramName].encodedValue = encodedValue;
decodedValueCache[paramName].decodedValue = decodedValue;
}
decodedValues[paramName] = decodedValue;
}
return decodedValues;
}, paramValues); // eslint-disable-line react-hooks/exhaustive-deps
// create a setter for updating multiple query params at once
var setQuery = React.useCallback(function (changes, updateType) {
// encode as strings for the URL
var encodedChanges = encodeQueryParams(paramConfigMap, changes);
// update the URL
updateUrlQuery(encodedChanges, refHistory.current.location || refLocation.current, // see #46
refHistory.current, updateType);
}, [paramConfigMap]);
}, [paramConfigMap, parsedQuery]);
// no longer Partial

@@ -81,0 +58,0 @@ return [decodedValues, setQuery];

import * as React from 'react';
import { QueryParamConfigMap, DecodedValueMap } from 'serialize-query-params';
import { SetQuery } from './types';
declare type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
declare type Diff<T, K> = Omit<T, keyof K>;
export interface InjectedQueryProps<QPCMap extends QueryParamConfigMap> {

@@ -15,3 +17,12 @@ query: DecodedValueMap<QPCMap>;

*/
export declare function withQueryParams<QPCMap extends QueryParamConfigMap, P extends InjectedQueryProps<QPCMap>>(paramConfigMap: QPCMap, WrappedComponent: React.ComponentType<P>): React.FunctionComponent<Pick<P, Exclude<keyof P, "query" | "setQuery">>>;
export declare function withQueryParams<QPCMap extends QueryParamConfigMap, P extends InjectedQueryProps<QPCMap>>(paramConfigMap: QPCMap, WrappedComponent: React.ComponentType<P>): React.FC<Pick<P, Exclude<keyof P, "query" | "setQuery">>>;
export default withQueryParams;
/**
* HOC to provide query parameters via props mapToProps (similar to
* react-redux connect style mapStateToProps)
* NOTE: I couldn't get type to automatically infer generic when
* using the format withQueryParams(config)(component), so I switched
* to withQueryParams(config, component).
* See: https://github.com/microsoft/TypeScript/issues/30134
*/
export declare function withQueryParamsMapped<QPCMap extends QueryParamConfigMap, MappedProps extends object, P extends MappedProps>(paramConfigMap: QPCMap, mapToProps: (query: DecodedValueMap<QPCMap>, setQuery: SetQuery<QPCMap>, props: Diff<P, MappedProps>) => MappedProps, WrappedComponent: React.ComponentType<P>): React.FC<Pick<P, Exclude<keyof P, keyof MappedProps>>>;

@@ -28,7 +28,24 @@ var __assign = (this && this.__assign) || function () {

};
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName ||
WrappedComponent.name ||
'Component') + ")";
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")";
return Component;
}
export default withQueryParams;
/**
* HOC to provide query parameters via props mapToProps (similar to
* react-redux connect style mapStateToProps)
* NOTE: I couldn't get type to automatically infer generic when
* using the format withQueryParams(config)(component), so I switched
* to withQueryParams(config, component).
* See: https://github.com/microsoft/TypeScript/issues/30134
*/
export function withQueryParamsMapped(paramConfigMap, mapToProps, WrappedComponent) {
// return a FC that takes props excluding query and setQuery
var Component = function (props) {
var _a = useQueryParams(paramConfigMap), query = _a[0], setQuery = _a[1];
var propsToAdd = mapToProps(query, setQuery, props);
// see https://github.com/microsoft/TypeScript/issues/28938#issuecomment-450636046 for why `...props as P`
return React.createElement(WrappedComponent, __assign({}, propsToAdd, props));
};
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")";
return Component;
}

@@ -5,5 +5,4 @@ export * from 'serialize-query-params';

export { useQueryParams } from './useQueryParams';
export { withQueryParams, InjectedQueryProps } from './withQueryParams';
export { withQueryParams, withQueryParamsMapped, InjectedQueryProps, } from './withQueryParams';
export { QueryParams, QueryParamsProps, QueryRenderProps } from './QueryParams';
export { updateUrlQuery } from './updateUrlQuery';
export { QueryParamProvider, QueryParamContext, QueryParamContextValue, } from './QueryParamProvider';
export { QueryParamProvider } from './QueryParamProvider';

@@ -13,8 +13,6 @@ "use strict";

exports.withQueryParams = withQueryParams_1.withQueryParams;
exports.withQueryParamsMapped = withQueryParams_1.withQueryParamsMapped;
var QueryParams_1 = require("./QueryParams");
exports.QueryParams = QueryParams_1.QueryParams;
var updateUrlQuery_1 = require("./updateUrlQuery");
exports.updateUrlQuery = updateUrlQuery_1.updateUrlQuery;
var QueryParamProvider_1 = require("./QueryParamProvider");
exports.QueryParamProvider = QueryParamProvider_1.QueryParamProvider;
exports.QueryParamContext = QueryParamProvider_1.QueryParamContext;
import * as React from 'react';
import { PushReplaceHistory } from './types';
import { HistoryLocation, PushReplaceHistory } from './types';
/**

@@ -14,10 +14,6 @@ * Subset of a @reach/router history object. We only

/**
* Shape of the QueryParamContext, needed to update the URL
* and know its current state.
* Helper to produce the context value falling back to
* window history and location if not provided.
*/
export interface QueryParamContextValue {
history: PushReplaceHistory;
location: Location;
}
export declare const QueryParamContext: React.Context<QueryParamContextValue>;
export declare function getLocationProps({ history, location, }?: Partial<HistoryLocation>): HistoryLocation;
/**

@@ -27,3 +23,3 @@ * Props for the Provider component, used to hook the active routing

*/
interface Props {
interface QueryParamProviderProps {
/** Main app goes here */

@@ -47,3 +43,3 @@ children: React.ReactNode;

*/
export declare function QueryParamProvider({ children, ReactRouterRoute, reachHistory, history, location, }: Props): JSX.Element;
export declare function QueryParamProvider({ children, ReactRouterRoute, reachHistory, history, location, }: QueryParamProviderProps): JSX.Element;
export default QueryParamProvider;

@@ -15,2 +15,6 @@ "use strict";

var React = require("react");
var LocationProvider_1 = require("./LocationProvider");
// we use a lazy caching solution to prevent #46 from happening
var cachedWindowHistory;
var cachedAdaptedWindowHistory;
/**

@@ -23,3 +27,6 @@ * Adapts standard DOM window history to work with our

function adaptWindowHistory(history) {
return {
if (history === cachedWindowHistory && cachedAdaptedWindowHistory != null) {
return cachedAdaptedWindowHistory;
}
var adaptedWindowHistory = {
replace: function (location) {

@@ -32,3 +39,9 @@ history.replaceState(location.state, '', location.protocol + "//" + location.host + location.pathname + location.search);

};
cachedWindowHistory = history;
cachedAdaptedWindowHistory = adaptedWindowHistory;
return adaptedWindowHistory;
}
// we use a lazy caching solution to prevent #46 from happening
var cachedReachHistory;
var cachedAdaptedReachHistory;
/**

@@ -41,3 +54,6 @@ * Adapts @reach/router history to work with our

function adaptReachHistory(history) {
return {
if (history === cachedReachHistory && cachedAdaptedReachHistory != null) {
return cachedAdaptedReachHistory;
}
var adaptedReachHistory = {
replace: function (location) {

@@ -50,2 +66,5 @@ history.navigate(location.protocol + "//" + location.host + location.pathname + location.search, { replace: true });

};
cachedReachHistory = history;
cachedAdaptedReachHistory = adaptedReachHistory;
return adaptedReachHistory;
}

@@ -56,17 +75,19 @@ /**

*/
function getContextValue(contextValue) {
if (contextValue === void 0) { contextValue = {}; }
var value = __assign({}, contextValue);
function getLocationProps(_a) {
var _b = _a === void 0 ? {} : _a, history = _b.history, location = _b.location;
var hasWindow = typeof window !== 'undefined';
if (hasWindow) {
if (!value.history) {
value.history = adaptWindowHistory(window.history);
if (!history) {
history = adaptWindowHistory(window.history);
}
if (!value.location) {
value.location = window.location;
if (!location) {
location = window.location;
}
}
return value;
if (!location) {
throw new Error("\n Could not read the location. Is the router wired up correctly?\n ");
}
return { history: history, location: location };
}
exports.QueryParamContext = React.createContext(getContextValue());
exports.getLocationProps = getLocationProps;
/**

@@ -81,3 +102,3 @@ * Context provider for query params to have access to the

return (React.createElement(ReactRouterRoute, null, function (routeProps) {
return (React.createElement(exports.QueryParamContext.Provider, { value: getContextValue(routeProps) }, children));
return (React.createElement(LocationProvider_1.LocationProvider, __assign({}, getLocationProps(routeProps)), children));
}));

@@ -87,11 +108,11 @@ }

if (reachHistory) {
return (React.createElement(exports.QueryParamContext.Provider, { value: getContextValue({
history: adaptReachHistory(reachHistory),
location: location,
}) }, children));
return (React.createElement(LocationProvider_1.LocationProvider, __assign({}, getLocationProps({
history: adaptReachHistory(reachHistory),
location: location,
})), children));
}
// neither reach nor react-router, so allow manual overrides
return (React.createElement(exports.QueryParamContext.Provider, { value: getContextValue({ history: history, location: location }) }, children));
return (React.createElement(LocationProvider_1.LocationProvider, __assign({}, getLocationProps({ history: history, location: location })), children));
}
exports.QueryParamProvider = QueryParamProvider;
exports.default = QueryParamProvider;

@@ -18,3 +18,2 @@ import { QueryParamConfigMap, DecodedValueMap } from 'serialize-query-params';

replace: (location: Location) => void;
location?: Location;
}

@@ -25,1 +24,10 @@ /**

export declare type SetQuery<QPCMap extends QueryParamConfigMap> = (changes: Partial<DecodedValueMap<QPCMap>>, updateType?: UrlUpdateType) => void;
export interface HistoryLocation {
/**
* History that meets the { replace, push } interface.
* May be missing when run server-side.
*/
history?: PushReplaceHistory;
/** The location object */
location: Location;
}

@@ -1,10 +0,14 @@

import { EncodedQueryWithNulls } from 'serialize-query-params';
import { EncodedQuery } from 'serialize-query-params';
import { PushReplaceHistory, UrlUpdateType } from './types';
/**
* Updates the URL to match the specified query changes.
* Creates a new location object containing the specified query changes.
* If replaceIn or pushIn are used as the updateType, then parameters
* not specified in queryReplacements are retained. If replace or push
* are used, only the values in queryReplacements will be available.
* The default is pushIn.
*/
export declare function updateUrlQuery(queryReplacements: EncodedQueryWithNulls, location: Location, history: PushReplaceHistory, updateType?: UrlUpdateType): void;
export default updateUrlQuery;
export declare function createLocationWithChanges(queryReplacements: EncodedQuery, location: Location, updateType?: UrlUpdateType): Location;
/**
* Updates the URL to the new location.
*/
export declare function updateUrlQuery(history: PushReplaceHistory, location: Location, updateType?: UrlUpdateType): void;

@@ -5,26 +5,38 @@ "use strict";

/**
* Updates the URL to match the specified query changes.
* Creates a new location object containing the specified query changes.
* If replaceIn or pushIn are used as the updateType, then parameters
* not specified in queryReplacements are retained. If replace or push
* are used, only the values in queryReplacements will be available.
* The default is pushIn.
*/
function updateUrlQuery(queryReplacements, location, history, updateType) {
if (updateType === void 0) { updateType = 'replaceIn'; }
function createLocationWithChanges(queryReplacements, location, updateType) {
if (updateType === void 0) { updateType = 'pushIn'; }
switch (updateType) {
case 'replace':
case 'push':
return serialize_query_params_1.updateLocation(queryReplacements, location);
case 'replaceIn':
history.replace(serialize_query_params_1.updateInLocation(queryReplacements, location));
break;
case 'pushIn':
history.push(serialize_query_params_1.updateInLocation(queryReplacements, location));
default:
return serialize_query_params_1.updateInLocation(queryReplacements, location);
}
}
exports.createLocationWithChanges = createLocationWithChanges;
/**
* Updates the URL to the new location.
*/
function updateUrlQuery(history, location, updateType) {
if (updateType === void 0) { updateType = 'pushIn'; }
switch (updateType) {
case 'pushIn':
case 'push':
history.push(location);
break;
case 'replaceIn':
case 'replace':
history.replace(serialize_query_params_1.updateLocation(queryReplacements, location));
default:
history.replace(location);
break;
case 'push':
history.push(serialize_query_params_1.updateLocation(queryReplacements, location));
break;
default:
}
}
exports.updateUrlQuery = updateUrlQuery;
exports.default = updateUrlQuery;

@@ -1,2 +0,2 @@

import { EncodedQueryWithNulls, QueryParamConfig } from 'serialize-query-params';
import { QueryParamConfig } from 'serialize-query-params';
/**

@@ -8,6 +8,6 @@ * Given a query param name and query parameter configuration ({ encode, decode })

* is one of 'replace' | 'replaceIn' | 'push' | 'pushIn', defaulting to
* 'replaceIn'.
* 'pushIn'.
*
* You may optionally pass in a rawQuery object, otherwise the query is derived
* from the location available in the QueryParamContext.
* from the location available in the context.
*

@@ -17,2 +17,2 @@ * D = decoded type

*/
export declare const useQueryParam: <D, D2 = D>(name: string, paramConfig?: QueryParamConfig<D, D2>, rawQuery?: EncodedQueryWithNulls | undefined) => [D2 | undefined, (newValue: D, updateType?: "replace" | "push" | "replaceIn" | "pushIn" | undefined) => void];
export declare const useQueryParam: <D, D2 = D>(name: string, paramConfig?: QueryParamConfig<D, D2>) => [D2 | undefined, (newValue: D, updateType?: "replace" | "push" | "replaceIn" | "pushIn" | undefined) => void];

@@ -5,4 +5,5 @@ "use strict";

var serialize_query_params_1 = require("serialize-query-params");
var QueryParamProvider_1 = require("./QueryParamProvider");
var updateUrlQuery_1 = require("./updateUrlQuery");
var helpers_1 = require("./helpers");
var LocationContext_1 = require("./LocationContext");
var memoizedQueryParser_1 = require("./memoizedQueryParser");
/**

@@ -14,6 +15,6 @@ * Given a query param name and query parameter configuration ({ encode, decode })

* is one of 'replace' | 'replaceIn' | 'push' | 'pushIn', defaulting to
* 'replaceIn'.
* 'pushIn'.
*
* You may optionally pass in a rawQuery object, otherwise the query is derived
* from the location available in the QueryParamContext.
* from the location available in the context.
*

@@ -23,66 +24,23 @@ * D = decoded type

*/
exports.useQueryParam = function (name, paramConfig, rawQuery) {
var _a;
exports.useQueryParam = function (name, paramConfig) {
if (paramConfig === void 0) { paramConfig = serialize_query_params_1.StringParam; }
var _b = React.useContext(QueryParamProvider_1.QueryParamContext), history = _b.history, location = _b.location;
// ref with current version history object (see #46)
var refHistory = React.useRef(history);
React.useEffect(function () {
refHistory.current = history;
}, [history]);
// ref with current version location object (see #46)
var refLocation = React.useRef(location);
React.useEffect(function () {
refLocation.current = location;
}, [location]);
var _a = LocationContext_1.useLocationContext(), location = _a[0], setLocation = _a[1];
// create the setter, memoizing via useCallback
var setValue = React.useCallback(function (newValue, updateType) {
var _a;
var newEncodedValue = paramConfig.encode(newValue);
setLocation((_a = {}, _a[name] = newEncodedValue, _a), updateType);
}, [paramConfig, name, setLocation]);
// read in the raw query
if (!rawQuery) {
var locationIsObject_1 = typeof location === 'object';
var windowIsDefined_1 = typeof window !== 'undefined';
rawQuery = React.useMemo(function () {
var pathname = {};
// handle checking SSR (#13)
if (locationIsObject_1) {
// in browser
if (windowIsDefined_1) {
pathname = serialize_query_params_1.parse(location.search);
}
else {
// not in browser
var url = location.pathname;
if (location.search) {
url += location.search;
}
pathname = serialize_query_params_1.parseUrl(url).query;
}
}
return pathname || {};
}, [location.search, location.pathname, locationIsObject_1, windowIsDefined_1]);
}
// read in the encoded string value
var encodedValue = rawQuery[name];
// note that we use the stringified encoded value since the encoded
// value may be an array that is recreated if a different query param
// changes. It is sufficient to use this instead of encodedValue in
// the useMemo dependency array since it will change any time the actual
// meaningful value of encodedValue changes.
var arraySafeEncodedValue = encodedValue instanceof Array
? serialize_query_params_1.stringify((_a = {}, _a[name] = encodedValue, _a))
: encodedValue;
var parsedQuery = memoizedQueryParser_1.sharedMemoizedQueryParser(helpers_1.getSSRSafeSearchString(location));
// read in the encoded string value (we have to use previous if available because
// sometimes the query string changes so we get a new parsedQuery but this value
// didn't change, so we should avoid generating a new array or whatever value)
var encodedValue = helpers_1.usePreviousIfShallowEqual(parsedQuery[name]);
// decode if the encoded value has changed, otherwise
// re-use memoized value
var decodedValue = React.useMemo(function () {
if (encodedValue == null) {
return undefined;
}
return paramConfig.decode(encodedValue);
}, [arraySafeEncodedValue, paramConfig]); // eslint-disable-line react-hooks/exhaustive-deps
// create the setter, memoizing via useCallback
var setValue = React.useCallback(function (newValue, updateType) {
var _a;
var newEncodedValue = paramConfig.encode(newValue);
updateUrlQuery_1.updateUrlQuery((_a = {}, _a[name] = newEncodedValue, _a), refHistory.current.location || refLocation.current, // see #46 for why we use a ref here
refHistory.current, updateType);
}, [paramConfig, name]);
}, [encodedValue, paramConfig]);
return [decodedValue, setValue];
};

@@ -5,23 +5,6 @@ "use strict";

var serialize_query_params_1 = require("serialize-query-params");
var useQueryParam_1 = require("./useQueryParam");
var updateUrlQuery_1 = require("./updateUrlQuery");
var QueryParamProvider_1 = require("./QueryParamProvider");
// from https://usehooks.com/usePrevious/
function usePrevious(value) {
var ref = React.useRef(value);
React.useEffect(function () {
ref.current = value;
}, [value]);
return ref.current;
}
// from https://github.com/lodash/lodash/issues/2340#issuecomment-360325395
function isShallowEqual(objA, objB) {
for (var key in objA)
if (!(key in objB) || objA[key] !== objB[key])
return false;
for (var key in objB)
if (!(key in objA) || objA[key] !== objB[key])
return false;
return true;
}
var helpers_1 = require("./helpers");
var LocationContext_1 = require("./LocationContext");
var memoizedQueryParser_1 = require("./memoizedQueryParser");
var shallowEqual_1 = require("./shallowEqual");
/**

@@ -32,52 +15,46 @@ * Given a query parameter configuration (mapping query param name to { encode, decode }),

exports.useQueryParams = function (paramConfigMap) {
var _a = React.useContext(QueryParamProvider_1.QueryParamContext), history = _a.history, location = _a.location;
var locationIsObject = typeof location === 'object';
var _a = LocationContext_1.useLocationContext(), location = _a[0], setLocation = _a[1];
var decodedValueCacheRef = React.useRef({});
// memoize paramConfigMap to make the API nicer for consumers.
// otherwise we'd have to useQueryParams(useMemo(() => { foo: NumberParam }, []))
var prevParamConfigMap = usePrevious(paramConfigMap);
var hasNewParamConfig = isShallowEqual(prevParamConfigMap, paramConfigMap);
// prettier-ignore
var memoParamConfigMap = React.useMemo(function () { return paramConfigMap; }, [
hasNewParamConfig,
]);
paramConfigMap = memoParamConfigMap;
// ref with current version history object (see #46)
var refHistory = React.useRef(history);
React.useEffect(function () {
refHistory.current = history;
}, [history]);
// ref with current version location object (see #46)
var refLocation = React.useRef(location);
React.useEffect(function () {
refLocation.current = location;
}, [location]);
var search = locationIsObject ? location.search : '';
paramConfigMap = helpers_1.usePreviousIfShallowEqual(paramConfigMap);
// create a setter for updating multiple query params at once
var setQuery = React.useCallback(function (changes, updateType) {
// encode as strings for the URL
var encodedChanges = serialize_query_params_1.encodeQueryParams(paramConfigMap, changes);
// update the URL
setLocation(encodedChanges, updateType);
}, [paramConfigMap, setLocation]);
// read in the raw query
var rawQuery = React.useMemo(function () { return serialize_query_params_1.parse(search) || {}; }, [
search,
]);
// parse each parameter via useQueryParam
// we reuse the logic to not recreate objects
var paramNames = Object.keys(paramConfigMap);
var paramValues = paramNames.map(function (paramName) {
return useQueryParam_1.useQueryParam(paramName, paramConfigMap[paramName], rawQuery)[0];
});
// we use a memo here to prevent recreating the containing decodedValues object
// which would break === comparisons even if no values changed.
var parsedQuery = memoizedQueryParser_1.sharedMemoizedQueryParser(helpers_1.getSSRSafeSearchString(location));
// decode all the values if we have changes
var decodedValues = React.useMemo(function () {
// iterate over the decoded values and build an object
var decodedValueCache = decodedValueCacheRef.current;
// we are decoding since the parsed query changed or the param config map has changed.
// recompute new values but only for those that changed
var paramNames = Object.keys(paramConfigMap);
var decodedValues = {};
for (var i = 0; i < paramNames.length; ++i) {
decodedValues[paramNames[i]] = paramValues[i];
for (var _i = 0, paramNames_1 = paramNames; _i < paramNames_1.length; _i++) {
var paramName = paramNames_1[_i];
var paramConfig = paramConfigMap[paramName];
var encodedValue = parsedQuery[paramName];
var decodedValue = void 0;
// re-use cached decoded value if we can, otherwise generate new
var cacheEntry = decodedValueCache[paramName];
if (cacheEntry != undefined &&
shallowEqual_1.default(cacheEntry.encodedValue, encodedValue)) {
decodedValue = cacheEntry.decodedValue;
}
else {
if (cacheEntry == null) {
decodedValueCache[paramName] = {};
}
decodedValue = paramConfig.decode(encodedValue);
decodedValueCache[paramName].encodedValue = encodedValue;
decodedValueCache[paramName].decodedValue = decodedValue;
}
decodedValues[paramName] = decodedValue;
}
return decodedValues;
}, paramValues); // eslint-disable-line react-hooks/exhaustive-deps
// create a setter for updating multiple query params at once
var setQuery = React.useCallback(function (changes, updateType) {
// encode as strings for the URL
var encodedChanges = serialize_query_params_1.encodeQueryParams(paramConfigMap, changes);
// update the URL
updateUrlQuery_1.default(encodedChanges, refHistory.current.location || refLocation.current, // see #46
refHistory.current, updateType);
}, [paramConfigMap]);
}, [paramConfigMap, parsedQuery]);
// no longer Partial

@@ -84,0 +61,0 @@ return [decodedValues, setQuery];

import * as React from 'react';
import { QueryParamConfigMap, DecodedValueMap } from 'serialize-query-params';
import { SetQuery } from './types';
declare type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
declare type Diff<T, K> = Omit<T, keyof K>;
export interface InjectedQueryProps<QPCMap extends QueryParamConfigMap> {

@@ -15,3 +17,12 @@ query: DecodedValueMap<QPCMap>;

*/
export declare function withQueryParams<QPCMap extends QueryParamConfigMap, P extends InjectedQueryProps<QPCMap>>(paramConfigMap: QPCMap, WrappedComponent: React.ComponentType<P>): React.FunctionComponent<Pick<P, Exclude<keyof P, "query" | "setQuery">>>;
export declare function withQueryParams<QPCMap extends QueryParamConfigMap, P extends InjectedQueryProps<QPCMap>>(paramConfigMap: QPCMap, WrappedComponent: React.ComponentType<P>): React.FC<Pick<P, Exclude<keyof P, "query" | "setQuery">>>;
export default withQueryParams;
/**
* HOC to provide query parameters via props mapToProps (similar to
* react-redux connect style mapStateToProps)
* NOTE: I couldn't get type to automatically infer generic when
* using the format withQueryParams(config)(component), so I switched
* to withQueryParams(config, component).
* See: https://github.com/microsoft/TypeScript/issues/30134
*/
export declare function withQueryParamsMapped<QPCMap extends QueryParamConfigMap, MappedProps extends object, P extends MappedProps>(paramConfigMap: QPCMap, mapToProps: (query: DecodedValueMap<QPCMap>, setQuery: SetQuery<QPCMap>, props: Diff<P, MappedProps>) => MappedProps, WrappedComponent: React.ComponentType<P>): React.FC<Pick<P, Exclude<keyof P, keyof MappedProps>>>;

@@ -30,5 +30,3 @@ "use strict";

};
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName ||
WrappedComponent.name ||
'Component') + ")";
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")";
return Component;

@@ -38,1 +36,21 @@ }

exports.default = withQueryParams;
/**
* HOC to provide query parameters via props mapToProps (similar to
* react-redux connect style mapStateToProps)
* NOTE: I couldn't get type to automatically infer generic when
* using the format withQueryParams(config)(component), so I switched
* to withQueryParams(config, component).
* See: https://github.com/microsoft/TypeScript/issues/30134
*/
function withQueryParamsMapped(paramConfigMap, mapToProps, WrappedComponent) {
// return a FC that takes props excluding query and setQuery
var Component = function (props) {
var _a = useQueryParams_1.default(paramConfigMap), query = _a[0], setQuery = _a[1];
var propsToAdd = mapToProps(query, setQuery, props);
// see https://github.com/microsoft/TypeScript/issues/28938#issuecomment-450636046 for why `...props as P`
return React.createElement(WrappedComponent, __assign({}, propsToAdd, props));
};
Component.displayName = "withQueryParams(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")";
return Component;
}
exports.withQueryParamsMapped = withQueryParamsMapped;
{
"name": "use-query-params",
"version": "0.6.0",
"version": "1.0.0",
"description": "React Hook for managing state in URL query parameters with easy serialization.",

@@ -44,14 +44,15 @@ "main": "lib/index.js",

"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.9.0",
"@testing-library/jest-dom": "^4.1.0",
"@testing-library/react": "^9.1.4",
"@testing-library/react-hooks": "^3.2.1",
"@types/jest": "^24.0.11",
"@types/react": "^16.8.25",
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/eslint-plugin": "^2.28.0",
"@typescript-eslint/parser": "^2.2.0",
"babel-jest": "^24.5.0",
"eslint": "^6.3.0",
"babel-jest": "^25.3.0",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.18.2",

@@ -61,10 +62,11 @@ "eslint-plugin-react": "^7.14.3",

"husky": "^3.0.5",
"jest": "^24.5.0",
"jest": "^25.3.0",
"lint-staged": "^9.2.5",
"prettier": "^1.18.2",
"prettier": "^2.0.4",
"query-string": "^6.12.1",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-hooks-testing-library": "^0.3.7",
"rimraf": "^3.0.0",
"typescript": "^3.3.3333"
"react-test-renderer": "^16.9.0",
"rimraf": "^3.0.2",
"typescript": "^3.8.3"
},

@@ -76,3 +78,3 @@ "peerDependencies": {

"dependencies": {
"serialize-query-params": "^0.3.0"
"serialize-query-params": "^1.0.1"
},

@@ -79,0 +81,0 @@ "husky": {

@@ -32,5 +32,7 @@ <div align="center">

```
$ npm install --save use-query-params
$ npm install --save use-query-params query-string
```
Note: There is a peer dependency on [query-string](https://github.com/sindresorhus/query-string). For IE11 support, use v5.1.1, otherwise use v6.
Link your routing system (e.g., [React Router example](https://github.com/pbeshai/use-query-params/blob/master/examples/react-router/src/index.tsx), [Reach Router example](https://github.com/pbeshai/use-query-params/blob/master/examples/reach-router/src/index.tsx)):

@@ -58,2 +60,4 @@

Be sure to add **QueryParamProvider** as shown in Installation above.
Add the hook to your component. There are two options: `useQueryParam`:

@@ -92,2 +96,3 @@

ArrayParam,
withDefault,
} from 'use-query-params';

@@ -100,5 +105,5 @@

q: StringParam,
filters: ArrayParam,
filters: withDefault(ArrayParam, []),
});
const { x: num, q: searchQuery, filters = [] } = query;
const { x: num, q: searchQuery, filters } = query;

@@ -137,6 +142,7 @@ return (

ArrayParam,
withDefault,
} from 'use-query-params';
const WithQueryParamsExample = ({ query, setQuery }: any) => {
const { x: num, q: searchQuery, filters = [] } = query;
const { x: num, q: searchQuery, filters } = query;

@@ -166,3 +172,3 @@ return (

q: StringParam,
filters: ArrayParam,
filters: withDefault(ArrayParam, []),
}, WithQueryParamsExample);

@@ -180,2 +186,3 @@ ```

ArrayParam,
withDefault,
} from 'use-query-params';

@@ -187,3 +194,3 @@

q: StringParam,
filters: ArrayParam,
filters: withDefault(ArrayParam, []),
};

@@ -194,3 +201,3 @@ return (

{({ query, setQuery }) => {
const { x: num, q: searchQuery, filters = [] } = query;
const { x: num, q: searchQuery, filters } = query;
return (

@@ -250,3 +257,3 @@ <>

For convenience, use-query-params exports all of the [serialize-query-params](https://github.com/pbeshai/serialize-query-params) library. This includes most functions from [query-string](https://github.com/sindresorhus/query-string), which is used internally.
For convenience, use-query-params exports all of the [serialize-query-params](https://github.com/pbeshai/serialize-query-params) library.

@@ -257,13 +264,18 @@ #### UrlUpdateType

- `'pushIn'`: Push just a single parameter, leaving the rest as is (back button works) (the default)
- `'push'`: Push all parameters with just those specified (back button works)
- `'replaceIn'`: Replace just a single parameter, leaving the rest as is
- `'replace'`: Replace all parameters with just those specified
- `'pushIn'`: Push just a single parameter, leaving the rest as is (back button works)
- `'push'`: Push all parameters with just those specified (back button works)
#### Param Types
See [all param definitions from serialize-query-params here](https://github.com/pbeshai/serialize-query-params/blob/master/src/params.ts). You can define your own parameter types by creating an object with an `encode` and a `decode` function. See the existing definitions for examples.
Note that all nully values will encode and decode as `undefined`.
Note that all null and empty values are typically treated as follows:
| value | encoding |
| --- | --- |
| `null` | `?qp` |
| `""` | `?qp=` |
| `undefined` | `?` (removed from URL) |
Examples in this table assume query parameter named `qp`.

@@ -333,3 +345,3 @@

You may optionally pass in a rawQuery object, otherwise the query is derived
from the location available in the QueryParamContext.
from the location in the context.

@@ -345,2 +357,5 @@ **Example**

setFoo(123, 'push');
// to unset or remove a parameter set it to undefined and use pushIn or replaceIn update types
setFoo(undefined) // ?foo=123&bar=zzz becomes ?bar=zzz
```

@@ -373,2 +388,5 @@

setQuery({ foo: 123, bar: 'zzz' }, 'push');
// to unset or remove a parameter set it to undefined and use pushIn or replaceIn update types
setQuery({ foo: undefined }) // ?foo=123&bar=zzz becomes ?bar=zzz
```

@@ -432,2 +450,4 @@

Note there is also a variant called `withQueryParamsMapped` that allows you to do a react-redux style mapStateToProps equivalent. See [the code](https://github.com/pbeshai/use-query-params/blob/master/src/withQueryParams.tsx#L51) or [this example](https://github.com/pbeshai/use-query-params/blob/master/examples/react-router/src/ReadmeExample3Mapped.tsx) for details.
<br/>

@@ -434,0 +454,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc