Socket
Socket
Sign inDemoInstall

use-location-state

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

use-location-state - npm Package Compare versions

Comparing version 2.3.1 to 2.4.0

dist/hooks/useRefLatest.d.ts

299

dist/use-location-state.cjs.js

@@ -11,14 +11,14 @@ 'use strict';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
Copyright (c) Microsoft Corporation.
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

@@ -75,71 +75,54 @@

function useQueryStateObj(defaultQueryState, queryStateOpts) {
var queryStringInterface = queryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface && { disabled: true });
var activeQSI = queryStringInterface || hashQSI;
var queryString = activeQSI.getQueryString();
var _a = react.useState(), setLatestMergedQueryString = _a[1];
var queryState = react.useMemo(function () { return (__assign(__assign({}, defaultQueryState), queryStateCore.parseQueryState(queryString))); }, [defaultQueryState, queryString]);
var ref = react.useRef({
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
});
var setQueryState = react.useCallback(function (newState, opts) {
var _a = ref.current, defaultQueryState = _a.defaultQueryState, queryStateOpts = _a.queryStateOpts, activeQSI = _a.activeQSI;
var _b = queryStateOpts.stripDefaults, stripDefaults = _b === void 0 ? true : _b;
var stripOverwrite = {};
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
Object.entries(newState).forEach(function (_a) {
var key = _a[0];
if (defaultQueryState[key] === newState[key]) {
stripOverwrite[key] = null;
}
});
}
// retrieve the last value (by re-executing the search getter)
var currentQueryState = __assign(__assign({}, defaultQueryState), queryStateCore.parseQueryState(activeQSI.getQueryString()));
var mergedQueryString = queryStateCore.createMergedQuery(currentQueryState || {}, newState, stripOverwrite);
activeQSI.setQueryString(mergedQueryString, opts || {});
// triggers an update (in case the QueryStringInterface misses to do so)
setLatestMergedQueryString(mergedQueryString);
}, []);
react.useEffect(function () {
ref.current = {
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
};
});
return [queryState, setQueryState];
function useRefLatest(value) {
var ref = react.useRef(value);
react.useLayoutEffect(function () {
ref.current = value;
}, [value]);
return ref;
}
function sameAsJsonString(compareValueA, compareValueB) {
return JSON.stringify(compareValueA) === JSON.stringify(compareValueB);
}
function useQueryState(itemName, defaultValue, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
defaultValue = react.useState(defaultValue)[0];
var defaultQueryStateValue = queryStateCore.toQueryStateValue(defaultValue);
var defaultQueryState = react.useMemo(function () {
var _a;
return defaultQueryStateValue
? (_a = {},
_a[itemName] = defaultQueryStateValue,
_a) : {};
}, [itemName, defaultQueryStateValue]);
var queryStateOptsDefaults = Object.freeze({});
function useQueryReducer(itemName, reducer, initialStateOrInitialArg, initStateFnOrOpts, queryStateOpts) {
var _a;
var mergedQueryStateOpts = Object.assign({}, queryStateOptsDefaults, queryStateOpts, typeof initStateFnOrOpts === 'object' ? initStateFnOrOpts : null);
var queryStringInterface = mergedQueryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface ? { disabled: true } : undefined);
var activeQSI = queryStringInterface || hashQSI;
// itemName & defaultValue is not allowed to be changed after init
var defaultValue = react.useState(function () {
return initStateFnOrOpts && typeof initStateFnOrOpts === 'function'
? initStateFnOrOpts(initialStateOrInitialArg)
: initialStateOrInitialArg;
})[0];
var defaultQueryStateValue = react.useMemo(function () { return queryStateCore.toQueryStateValue(defaultValue); }, [defaultValue]);
if (defaultQueryStateValue === null) {
throw new Error('unsupported defaultValue');
}
var _a = useQueryStateObj(defaultQueryState, queryStateOpts), queryState = _a[0], setQueryState = _a[1];
var setQueryStateItem = react.useCallback(function (newValue, opts) {
var ref = useRefLatest({
activeQSI: activeQSI,
defaultValue: defaultValue,
mergedQueryStateOpts: mergedQueryStateOpts,
reducer: reducer,
});
var resetQueryStateItem = react.useCallback(function (opts) {
var _a;
// stringify the given value (or array of strings)
var activeQSI = ref.current.activeQSI;
var currentState = queryStateCore.parseQueryState(activeQSI.getQueryString()) || {};
var newState = __assign(__assign({}, currentState), (_a = {}, _a[itemName] = null, _a));
activeQSI.setQueryString(queryStateCore.createMergedQuery(newState), opts);
setR(function (rC) { return rC + 1; });
}, [itemName, ref]);
var _b = react.useState(0), setR = _b[1];
var dispatch = react.useCallback(function (action, opts) {
var _a;
if (opts === void 0) { opts = {}; }
var _b = ref.current, activeQSI = _b.activeQSI, defaultValue = _b.defaultValue, mergedQueryStateOpts = _b.mergedQueryStateOpts, reducer = _b.reducer;
var _c = mergedQueryStateOpts.stripDefaults, stripDefaults = _c === void 0 ? true : _c;
var currentState = queryStateCore.parseQueryState(activeQSI.getQueryString()) || {};
var currentValue = itemName in currentState
? queryStateCore.parseQueryStateValue(currentState[itemName], defaultValue)
: defaultValue;
var newValue = reducer(currentValue !== null && currentValue !== void 0 ? currentValue : defaultValue, action);
var newQueryStateValue = queryStateCore.toQueryStateValue(newValue);
// warn when value type is not supported (do not warn when null was passed explicitly)
if ((newQueryStateValue === null && newValue !== newQueryStateValue) ||
!(newQueryStateValue !== null &&
typeof queryStateCore.parseQueryStateValue(newQueryStateValue, defaultValue) === typeof defaultValue)) {
if (newQueryStateValue === null) {
console.warn('value of ' +

@@ -149,32 +132,40 @@ JSON.stringify(newValue) +

itemName +
'" will reset to default value', defaultValue);
newQueryStateValue = null;
'" will reset to default value of:', defaultValue);
}
// when new value is equal to default, we call setQueryState with a null value to reset query string
// arrays have to be compared json stringified, other values can compared by value
if (Array.isArray(defaultValue) && sameAsJsonString(newValue, defaultValue)) {
newQueryStateValue = null;
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
if (Array.isArray(defaultValue) && sameAsJsonString(newValue, defaultValue)) {
return resetQueryStateItem(opts);
}
else if (newValue === defaultValue) {
return resetQueryStateItem(opts);
}
}
else if (newValue === defaultValue) {
newQueryStateValue = null;
}
setQueryState((_a = {}, _a[itemName] = newQueryStateValue, _a), opts);
}, [defaultValue, itemName, setQueryState]);
// fallback to default value
var value = defaultValue;
var queryStateItem = queryState[itemName];
var queryStateValue = null;
if (queryStateItem || queryStateItem === '') {
queryStateValue = queryStateCore.parseQueryStateValue(queryStateItem, defaultValue);
}
if (queryStateValue !== null && typeof queryStateValue === typeof defaultValue) {
value = queryStateValue;
}
return [value, setQueryStateItem];
activeQSI.setQueryString(queryStateCore.createMergedQuery(__assign(__assign({}, currentState), (_a = {}, _a[itemName] = queryStateCore.toQueryStateValue(newValue), _a))), opts);
// force re-render
setR(function (rC) { return rC + 1; });
}, [itemName, ref, resetQueryStateItem]);
var currentState = queryStateCore.parseQueryState(activeQSI.getQueryString()) || {};
var currentValue = (_a = (itemName in currentState
? queryStateCore.parseQueryStateValue(currentState[itemName], defaultValue)
: defaultValue)) !== null && _a !== void 0 ? _a : defaultValue;
return [currentValue, dispatch];
}
function sameAsJsonString(compareValueA, compareValueB) {
return JSON.stringify(compareValueA) === JSON.stringify(compareValueB);
}
function useHashQueryState(itemName, defaultValue, queryStateOpts) {
function useQueryState(itemName, initialState, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryState(itemName, defaultValue, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
var reducer = react.useCallback(function (prevState, action) {
if (action && typeof action === 'function') {
return action(prevState);
}
return action;
}, []);
if (typeof initialState === 'function') {
return useQueryReducer(itemName, reducer, undefined, initialState, queryStateOpts);
}
return useQueryReducer(itemName, reducer, initialState, queryStateOpts);
}

@@ -217,7 +208,7 @@

return;
var hashChangeHandler = function () {
var popstateHandler = function () {
setR(function (r) { return r + 1; });
};
window.addEventListener('popstate', hashChangeHandler, false);
return function () { return window.removeEventListener('popstate', hashChangeHandler, false); };
window.addEventListener('popstate', popstateHandler, false);
return function () { return window.removeEventListener('popstate', popstateHandler, false); };
}, [enabled]);

@@ -229,5 +220,12 @@ return locationStateInterface;

var locationStateOptsDefaults = Object.freeze({});
function useLocationState(itemName, defaultValue, _a) {
var locationStateInterface = (_a === void 0 ? locationStateOptsDefaults : _a).locationStateInterface;
defaultValue = react.useState(defaultValue)[0];
function useLocationReducer(itemName, reducer, initialStateOrInitialArg, maybeInitStateFnOrOpts, opts) {
var locationStateInterface = (opts ||
(typeof maybeInitStateFnOrOpts === 'object' && maybeInitStateFnOrOpts) ||
locationStateOptsDefaults).locationStateInterface;
// itemName & defaultValue is not allowed to be changed after init
var defaultValue = react.useState(function () {
return maybeInitStateFnOrOpts && typeof maybeInitStateFnOrOpts === 'function'
? maybeInitStateFnOrOpts(initialStateOrInitialArg)
: initialStateOrInitialArg;
})[0];
// throw for invalid values like functions

@@ -238,3 +236,3 @@ if (!validTypes.includes(typeof defaultValue)) {

itemName = react.useState(function () {
var suffixObscurer = typeof btoa !== "undefined" ? btoa : (function (s) { return s; });
var suffixObscurer = typeof btoa !== 'undefined' ? btoa : function (s) { return s; };
var suffix = suffixObscurer(Array.isArray(defaultValue) ? 'array' : typeof defaultValue).replace(/=/g, '');

@@ -246,4 +244,5 @@ return itemName + "__" + suffix;

var activeLSI = locationStateInterface || standardLSI;
var ref = react.useRef({
var ref = useRefLatest({
activeLSI: activeLSI,
reducer: reducer,
});

@@ -263,17 +262,10 @@ var currentState = activeLSI.getLocationState();

activeLSI.setLocationState(newState, opts);
}, [itemName]);
var setLocationStateItem = react.useCallback(function (newValueOrFn, opts) {
}, [itemName, ref]);
var dispatchAction = react.useCallback(function (action, opts) {
var _a;
if (opts === void 0) { opts = {}; }
var _b = ref.current.activeLSI, getLocationState = _b.getLocationState, setLocationState = _b.setLocationState;
var newValue;
var _b = ref.current, reducer = _b.reducer, _c = _b.activeLSI, getLocationState = _c.getLocationState, setLocationState = _c.setLocationState;
var currentState = getLocationState();
var currentValue = itemName in currentState ? currentState[itemName] : defaultValue;
if (typeof newValueOrFn === 'function') {
// @ts-ignore
newValue = newValueOrFn(currentValue);
}
else {
newValue = newValueOrFn;
}
var newValue = reducer(currentValue, action);
if (newValue === defaultValue) {

@@ -290,15 +282,82 @@ return resetLocationStateItem(opts);

_a);
setLocationState(__assign(__assign({}, getLocationState()), stateExtendOverwrite), opts);
}, [defaultValue, itemName, resetLocationStateItem]);
setLocationState(__assign(__assign({}, currentState), stateExtendOverwrite), opts);
}, [defaultValue, itemName, ref, resetLocationStateItem]);
return [value, dispatchAction];
}
var locationStateOptsDefaults$1 = Object.freeze({});
function useLocationState(itemName, initialState, opts) {
if (opts === void 0) { opts = locationStateOptsDefaults$1; }
if (typeof initialState === 'function') {
return useLocationReducer(itemName, stateReducer, undefined, initialState, opts);
}
return useLocationReducer(itemName, stateReducer, initialState, opts);
}
function stateReducer(prevState, action) {
if (action && typeof action === 'function') {
return action(prevState);
}
return action;
}
function useQueryStateObj(defaultQueryState, queryStateOpts) {
var queryStringInterface = queryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface && { disabled: true });
var activeQSI = queryStringInterface || hashQSI;
var queryString = activeQSI.getQueryString();
var _a = react.useState(), setLatestMergedQueryString = _a[1];
var queryState = react.useMemo(function () { return (__assign(__assign({}, defaultQueryState), queryStateCore.parseQueryState(queryString))); }, [defaultQueryState, queryString]);
var ref = react.useRef({
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
});
var setQueryState = react.useCallback(function (newState, opts) {
var _a = ref.current, defaultQueryState = _a.defaultQueryState, queryStateOpts = _a.queryStateOpts, activeQSI = _a.activeQSI;
var _b = queryStateOpts.stripDefaults, stripDefaults = _b === void 0 ? true : _b;
var stripOverwrite = {};
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
Object.entries(newState).forEach(function (_a) {
var key = _a[0];
if (defaultQueryState[key] === newState[key]) {
stripOverwrite[key] = null;
}
});
}
// retrieve the last value (by re-executing the search getter)
var currentQueryState = __assign(__assign({}, defaultQueryState), queryStateCore.parseQueryState(activeQSI.getQueryString()));
var mergedQueryString = queryStateCore.createMergedQuery(currentQueryState || {}, newState, stripOverwrite);
activeQSI.setQueryString(mergedQueryString, opts || {});
// triggers an update (in case the QueryStringInterface misses to do so)
setLatestMergedQueryString(mergedQueryString);
}, []);
react.useEffect(function () {
ref.current = {
activeLSI: activeLSI,
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
};
});
return [value, setLocationStateItem];
return [queryState, setQueryState];
}
function useHashQueryStateObj(defaultQueryState, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryStateObj(defaultQueryState, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
}
function useHashQueryState(itemName, defaultValue, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryState(itemName, defaultValue, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
}
exports.LOCATION_STATE_KEY = LOCATION_STATE_KEY;
exports.useHashQueryState = useHashQueryState;
exports.useHashQueryStateObj = useHashQueryStateObj;
exports.useLocationReducer = useLocationReducer;
exports.useLocationState = useLocationState;
exports.useQueryReducer = useQueryReducer;
exports.useQueryState = useQueryState;
export * from './useQueryState/useQueryState.types';
export * from './useLocationState/useLocationState.types';
export { default as useQueryState } from './useQueryState/useQueryState';
export { default as useHashQueryState } from './useQueryState/useHashQueryState';
export { default as useLocationState } from './useLocationState/useLocationState';
export * from './types/sharedTypes';
export * from './useQueryState/useQueryState';
export * from './useQueryState/useQueryReducer';
export * from './useLocationState/useLocationState';
export * from './useLocationState/useLocationReducer';
export * from './useQueryState/useHashQueryState';

@@ -1,3 +0,3 @@

import { useMemo, useState, useEffect, useRef, useCallback } from 'react';
import { parseQueryState, createMergedQuery, toQueryStateValue, parseQueryStateValue } from 'query-state-core';
import { useMemo, useState, useEffect, useRef, useLayoutEffect, useCallback } from 'react';
import { toQueryStateValue, parseQueryState, createMergedQuery, parseQueryStateValue } from 'query-state-core';

@@ -7,14 +7,14 @@ var LOCATION_STATE_KEY = '__useLocationState';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
Copyright (c) Microsoft Corporation.
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

@@ -71,71 +71,54 @@

function useQueryStateObj(defaultQueryState, queryStateOpts) {
var queryStringInterface = queryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface && { disabled: true });
var activeQSI = queryStringInterface || hashQSI;
var queryString = activeQSI.getQueryString();
var _a = useState(), setLatestMergedQueryString = _a[1];
var queryState = useMemo(function () { return (__assign(__assign({}, defaultQueryState), parseQueryState(queryString))); }, [defaultQueryState, queryString]);
var ref = useRef({
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
});
var setQueryState = useCallback(function (newState, opts) {
var _a = ref.current, defaultQueryState = _a.defaultQueryState, queryStateOpts = _a.queryStateOpts, activeQSI = _a.activeQSI;
var _b = queryStateOpts.stripDefaults, stripDefaults = _b === void 0 ? true : _b;
var stripOverwrite = {};
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
Object.entries(newState).forEach(function (_a) {
var key = _a[0];
if (defaultQueryState[key] === newState[key]) {
stripOverwrite[key] = null;
}
});
}
// retrieve the last value (by re-executing the search getter)
var currentQueryState = __assign(__assign({}, defaultQueryState), parseQueryState(activeQSI.getQueryString()));
var mergedQueryString = createMergedQuery(currentQueryState || {}, newState, stripOverwrite);
activeQSI.setQueryString(mergedQueryString, opts || {});
// triggers an update (in case the QueryStringInterface misses to do so)
setLatestMergedQueryString(mergedQueryString);
}, []);
useEffect(function () {
ref.current = {
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
};
});
return [queryState, setQueryState];
function useRefLatest(value) {
var ref = useRef(value);
useLayoutEffect(function () {
ref.current = value;
}, [value]);
return ref;
}
function sameAsJsonString(compareValueA, compareValueB) {
return JSON.stringify(compareValueA) === JSON.stringify(compareValueB);
}
function useQueryState(itemName, defaultValue, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
defaultValue = useState(defaultValue)[0];
var defaultQueryStateValue = toQueryStateValue(defaultValue);
var defaultQueryState = useMemo(function () {
var _a;
return defaultQueryStateValue
? (_a = {},
_a[itemName] = defaultQueryStateValue,
_a) : {};
}, [itemName, defaultQueryStateValue]);
var queryStateOptsDefaults = Object.freeze({});
function useQueryReducer(itemName, reducer, initialStateOrInitialArg, initStateFnOrOpts, queryStateOpts) {
var _a;
var mergedQueryStateOpts = Object.assign({}, queryStateOptsDefaults, queryStateOpts, typeof initStateFnOrOpts === 'object' ? initStateFnOrOpts : null);
var queryStringInterface = mergedQueryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface ? { disabled: true } : undefined);
var activeQSI = queryStringInterface || hashQSI;
// itemName & defaultValue is not allowed to be changed after init
var defaultValue = useState(function () {
return initStateFnOrOpts && typeof initStateFnOrOpts === 'function'
? initStateFnOrOpts(initialStateOrInitialArg)
: initialStateOrInitialArg;
})[0];
var defaultQueryStateValue = useMemo(function () { return toQueryStateValue(defaultValue); }, [defaultValue]);
if (defaultQueryStateValue === null) {
throw new Error('unsupported defaultValue');
}
var _a = useQueryStateObj(defaultQueryState, queryStateOpts), queryState = _a[0], setQueryState = _a[1];
var setQueryStateItem = useCallback(function (newValue, opts) {
var ref = useRefLatest({
activeQSI: activeQSI,
defaultValue: defaultValue,
mergedQueryStateOpts: mergedQueryStateOpts,
reducer: reducer,
});
var resetQueryStateItem = useCallback(function (opts) {
var _a;
// stringify the given value (or array of strings)
var activeQSI = ref.current.activeQSI;
var currentState = parseQueryState(activeQSI.getQueryString()) || {};
var newState = __assign(__assign({}, currentState), (_a = {}, _a[itemName] = null, _a));
activeQSI.setQueryString(createMergedQuery(newState), opts);
setR(function (rC) { return rC + 1; });
}, [itemName, ref]);
var _b = useState(0), setR = _b[1];
var dispatch = useCallback(function (action, opts) {
var _a;
if (opts === void 0) { opts = {}; }
var _b = ref.current, activeQSI = _b.activeQSI, defaultValue = _b.defaultValue, mergedQueryStateOpts = _b.mergedQueryStateOpts, reducer = _b.reducer;
var _c = mergedQueryStateOpts.stripDefaults, stripDefaults = _c === void 0 ? true : _c;
var currentState = parseQueryState(activeQSI.getQueryString()) || {};
var currentValue = itemName in currentState
? parseQueryStateValue(currentState[itemName], defaultValue)
: defaultValue;
var newValue = reducer(currentValue !== null && currentValue !== void 0 ? currentValue : defaultValue, action);
var newQueryStateValue = toQueryStateValue(newValue);
// warn when value type is not supported (do not warn when null was passed explicitly)
if ((newQueryStateValue === null && newValue !== newQueryStateValue) ||
!(newQueryStateValue !== null &&
typeof parseQueryStateValue(newQueryStateValue, defaultValue) === typeof defaultValue)) {
if (newQueryStateValue === null) {
console.warn('value of ' +

@@ -145,32 +128,40 @@ JSON.stringify(newValue) +

itemName +
'" will reset to default value', defaultValue);
newQueryStateValue = null;
'" will reset to default value of:', defaultValue);
}
// when new value is equal to default, we call setQueryState with a null value to reset query string
// arrays have to be compared json stringified, other values can compared by value
if (Array.isArray(defaultValue) && sameAsJsonString(newValue, defaultValue)) {
newQueryStateValue = null;
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
if (Array.isArray(defaultValue) && sameAsJsonString(newValue, defaultValue)) {
return resetQueryStateItem(opts);
}
else if (newValue === defaultValue) {
return resetQueryStateItem(opts);
}
}
else if (newValue === defaultValue) {
newQueryStateValue = null;
}
setQueryState((_a = {}, _a[itemName] = newQueryStateValue, _a), opts);
}, [defaultValue, itemName, setQueryState]);
// fallback to default value
var value = defaultValue;
var queryStateItem = queryState[itemName];
var queryStateValue = null;
if (queryStateItem || queryStateItem === '') {
queryStateValue = parseQueryStateValue(queryStateItem, defaultValue);
}
if (queryStateValue !== null && typeof queryStateValue === typeof defaultValue) {
value = queryStateValue;
}
return [value, setQueryStateItem];
activeQSI.setQueryString(createMergedQuery(__assign(__assign({}, currentState), (_a = {}, _a[itemName] = toQueryStateValue(newValue), _a))), opts);
// force re-render
setR(function (rC) { return rC + 1; });
}, [itemName, ref, resetQueryStateItem]);
var currentState = parseQueryState(activeQSI.getQueryString()) || {};
var currentValue = (_a = (itemName in currentState
? parseQueryStateValue(currentState[itemName], defaultValue)
: defaultValue)) !== null && _a !== void 0 ? _a : defaultValue;
return [currentValue, dispatch];
}
function sameAsJsonString(compareValueA, compareValueB) {
return JSON.stringify(compareValueA) === JSON.stringify(compareValueB);
}
function useHashQueryState(itemName, defaultValue, queryStateOpts) {
function useQueryState(itemName, initialState, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryState(itemName, defaultValue, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
var reducer = useCallback(function (prevState, action) {
if (action && typeof action === 'function') {
return action(prevState);
}
return action;
}, []);
if (typeof initialState === 'function') {
return useQueryReducer(itemName, reducer, undefined, initialState, queryStateOpts);
}
return useQueryReducer(itemName, reducer, initialState, queryStateOpts);
}

@@ -213,7 +204,7 @@

return;
var hashChangeHandler = function () {
var popstateHandler = function () {
setR(function (r) { return r + 1; });
};
window.addEventListener('popstate', hashChangeHandler, false);
return function () { return window.removeEventListener('popstate', hashChangeHandler, false); };
window.addEventListener('popstate', popstateHandler, false);
return function () { return window.removeEventListener('popstate', popstateHandler, false); };
}, [enabled]);

@@ -225,5 +216,12 @@ return locationStateInterface;

var locationStateOptsDefaults = Object.freeze({});
function useLocationState(itemName, defaultValue, _a) {
var locationStateInterface = (_a === void 0 ? locationStateOptsDefaults : _a).locationStateInterface;
defaultValue = useState(defaultValue)[0];
function useLocationReducer(itemName, reducer, initialStateOrInitialArg, maybeInitStateFnOrOpts, opts) {
var locationStateInterface = (opts ||
(typeof maybeInitStateFnOrOpts === 'object' && maybeInitStateFnOrOpts) ||
locationStateOptsDefaults).locationStateInterface;
// itemName & defaultValue is not allowed to be changed after init
var defaultValue = useState(function () {
return maybeInitStateFnOrOpts && typeof maybeInitStateFnOrOpts === 'function'
? maybeInitStateFnOrOpts(initialStateOrInitialArg)
: initialStateOrInitialArg;
})[0];
// throw for invalid values like functions

@@ -234,3 +232,3 @@ if (!validTypes.includes(typeof defaultValue)) {

itemName = useState(function () {
var suffixObscurer = typeof btoa !== "undefined" ? btoa : (function (s) { return s; });
var suffixObscurer = typeof btoa !== 'undefined' ? btoa : function (s) { return s; };
var suffix = suffixObscurer(Array.isArray(defaultValue) ? 'array' : typeof defaultValue).replace(/=/g, '');

@@ -242,4 +240,5 @@ return itemName + "__" + suffix;

var activeLSI = locationStateInterface || standardLSI;
var ref = useRef({
var ref = useRefLatest({
activeLSI: activeLSI,
reducer: reducer,
});

@@ -259,17 +258,10 @@ var currentState = activeLSI.getLocationState();

activeLSI.setLocationState(newState, opts);
}, [itemName]);
var setLocationStateItem = useCallback(function (newValueOrFn, opts) {
}, [itemName, ref]);
var dispatchAction = useCallback(function (action, opts) {
var _a;
if (opts === void 0) { opts = {}; }
var _b = ref.current.activeLSI, getLocationState = _b.getLocationState, setLocationState = _b.setLocationState;
var newValue;
var _b = ref.current, reducer = _b.reducer, _c = _b.activeLSI, getLocationState = _c.getLocationState, setLocationState = _c.setLocationState;
var currentState = getLocationState();
var currentValue = itemName in currentState ? currentState[itemName] : defaultValue;
if (typeof newValueOrFn === 'function') {
// @ts-ignore
newValue = newValueOrFn(currentValue);
}
else {
newValue = newValueOrFn;
}
var newValue = reducer(currentValue, action);
if (newValue === defaultValue) {

@@ -286,12 +278,76 @@ return resetLocationStateItem(opts);

_a);
setLocationState(__assign(__assign({}, getLocationState()), stateExtendOverwrite), opts);
}, [defaultValue, itemName, resetLocationStateItem]);
setLocationState(__assign(__assign({}, currentState), stateExtendOverwrite), opts);
}, [defaultValue, itemName, ref, resetLocationStateItem]);
return [value, dispatchAction];
}
var locationStateOptsDefaults$1 = Object.freeze({});
function useLocationState(itemName, initialState, opts) {
if (opts === void 0) { opts = locationStateOptsDefaults$1; }
if (typeof initialState === 'function') {
return useLocationReducer(itemName, stateReducer, undefined, initialState, opts);
}
return useLocationReducer(itemName, stateReducer, initialState, opts);
}
function stateReducer(prevState, action) {
if (action && typeof action === 'function') {
return action(prevState);
}
return action;
}
function useQueryStateObj(defaultQueryState, queryStateOpts) {
var queryStringInterface = queryStateOpts.queryStringInterface;
var hashQSI = useHashQueryStringInterface(queryStringInterface && { disabled: true });
var activeQSI = queryStringInterface || hashQSI;
var queryString = activeQSI.getQueryString();
var _a = useState(), setLatestMergedQueryString = _a[1];
var queryState = useMemo(function () { return (__assign(__assign({}, defaultQueryState), parseQueryState(queryString))); }, [defaultQueryState, queryString]);
var ref = useRef({
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
});
var setQueryState = useCallback(function (newState, opts) {
var _a = ref.current, defaultQueryState = _a.defaultQueryState, queryStateOpts = _a.queryStateOpts, activeQSI = _a.activeQSI;
var _b = queryStateOpts.stripDefaults, stripDefaults = _b === void 0 ? true : _b;
var stripOverwrite = {};
// when a params are set to the same value as in the defaults
// we remove them to avoid having two URLs reproducing the same state unless stripDefaults === false
if (stripDefaults) {
Object.entries(newState).forEach(function (_a) {
var key = _a[0];
if (defaultQueryState[key] === newState[key]) {
stripOverwrite[key] = null;
}
});
}
// retrieve the last value (by re-executing the search getter)
var currentQueryState = __assign(__assign({}, defaultQueryState), parseQueryState(activeQSI.getQueryString()));
var mergedQueryString = createMergedQuery(currentQueryState || {}, newState, stripOverwrite);
activeQSI.setQueryString(mergedQueryString, opts || {});
// triggers an update (in case the QueryStringInterface misses to do so)
setLatestMergedQueryString(mergedQueryString);
}, []);
useEffect(function () {
ref.current = {
activeLSI: activeLSI,
defaultQueryState: defaultQueryState,
queryStateOpts: queryStateOpts,
activeQSI: activeQSI,
};
});
return [value, setLocationStateItem];
return [queryState, setQueryState];
}
export { LOCATION_STATE_KEY, useHashQueryState, useLocationState, useQueryState };
function useHashQueryStateObj(defaultQueryState, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryStateObj(defaultQueryState, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
}
function useHashQueryState(itemName, defaultValue, queryStateOpts) {
if (queryStateOpts === void 0) { queryStateOpts = {}; }
var hashQSI = useHashQueryStringInterface();
return useQueryState(itemName, defaultValue, __assign(__assign({}, queryStateOpts), { queryStringInterface: hashQSI }));
}
export { LOCATION_STATE_KEY, useHashQueryState, useHashQueryStateObj, useLocationReducer, useLocationState, useQueryReducer, useQueryState };

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

import { LocationStateOpts, SetLocationState } from './useLocationState.types';
export default function useLocationState<S>(itemName: string, defaultValue: S | (() => S), { locationStateInterface }?: LocationStateOpts): [S, SetLocationState<S>];
import { LocationStateOpts } from './useLocationState.types';
import { LocationDispatch } from './useLocationReducer';
import { LazyValueFn, SetStateAction } from '../types/sharedTypes';
export declare function useLocationState<S>(itemName: string, initialState: S | LazyValueFn<S>, opts?: LocationStateOpts): [S, LocationDispatch<SetStateAction<S>>];

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

import { SetStateAction } from '../types/sharedTypes';
export declare const LOCATION_STATE_KEY = "__useLocationState";

@@ -14,4 +15,2 @@ export declare type LocationStateValue<K = unknown> = string | number | boolean | undefined | Date | Array<K>;

}
declare type SetStateAction<S> = S | ((prevState: S) => S);
export declare type SetLocationState<T> = (newValue: SetStateAction<T>, opts?: SetLocationStateOptions) => void;
export {};
import { QueryState } from 'query-state-core';
import { QueryStateOptsSetInterface } from './useQueryState.types';
import { QueryStateOptsSetInterface, QueryStateType } from './useQueryState.types';
export declare function useHashQueryStateObj<T extends QueryState>(defaultQueryState: T, queryStateOpts?: QueryStateOptsSetInterface): [Record<string, import("query-state-core").QueryStateValue>, import("./useQueryState.types").SetQueryStateFn<T>];
export default function useHashQueryState<T>(itemName: string, defaultValue: T, queryStateOpts?: QueryStateOptsSetInterface): [T, import("./useQueryState.types").SetQueryStateItemFn<T>];
export declare function useHashQueryState<T extends QueryStateType>(itemName: string, defaultValue: T, queryStateOpts?: QueryStateOptsSetInterface): [T, import("./useQueryReducer").QueryDispatch<import("../use-location-state").SetStateAction<T>>];

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

import { QueryStateOpts, SetQueryStateItemFn } from './useQueryState.types';
export default function useQueryState<T>(itemName: string, defaultValue: T, queryStateOpts?: QueryStateOpts): [T, SetQueryStateItemFn<T>];
import { QueryStateOpts } from './useQueryState.types';
import { QueryDispatch } from './useQueryReducer';
import { LazyValueFn, SetStateAction } from '../types/sharedTypes';
export declare function useQueryState<S>(itemName: string, initialState: S | LazyValueFn<S>, queryStateOpts?: QueryStateOpts): [S, QueryDispatch<SetStateAction<S>>];
import { QueryStateMerge } from 'query-state-core';
export declare type QueryString = string;
export declare type SetQueryStateFn<T> = (newState: QueryStateMerge, opts?: SetQueryStringOptions) => void;
export declare type SetQueryStateItemFn<T> = (newValue: T, opts?: SetQueryStringOptions) => void;
export interface QueryStringInterface {

@@ -19,1 +18,2 @@ getQueryString: () => QueryString;

};
export declare type QueryStateType = string | number | boolean | Date | string[];
import { QueryState } from 'query-state-core';
import { QueryStateOpts, SetQueryStateFn } from './useQueryState.types';
export default function useQueryStateObj<T extends QueryState>(defaultQueryState: T, queryStateOpts: QueryStateOpts): [QueryState, SetQueryStateFn<T>];
export declare function useQueryStateObj<T extends QueryState>(defaultQueryState: T, queryStateOpts: QueryStateOpts): [QueryState, SetQueryStateFn<T>];

@@ -11,5 +11,5 @@ {

"dependencies": {
"query-state-core": "^2.3.0"
"query-state-core": "^2.4.0"
},
"version": "2.3.1",
"version": "2.4.0",
"author": "Felix Leupold <felix@xiel.de>",

@@ -21,6 +21,6 @@ "homepage": "https://github.com/xiel/use-location-state",

"react": "^16.9.0",
"rollup": "^1.19.3",
"rollup-plugin-typescript2": "^0.24.0",
"tslib": "^1.9.3",
"typescript": "^3.6.3"
"rollup": ">=2.0.0",
"rollup-plugin-typescript2": ">=0.26.0",
"tslib": "*",
"typescript": "*"
},

@@ -43,3 +43,3 @@ "files": [

},
"gitHead": "2248d0e2266c0e971551fe70bcf82fb6941ff2c2"
"gitHead": "378cd4bffb30a0f96f0d68b1959fb5050114a5cc"
}

@@ -1,5 +0,6 @@

<h1 style="width: 100%; text-align: center;"> { useLocationState, useQueryState }</h1>
<div style="width: 100%; text-align: center;">
<h1>{ useLocationState, useQueryState }</h1>
</div>
[![npm (tag)](https://img.shields.io/npm/v/use-location-state/latest.svg)](https://www.npmjs.com/package/use-location-state)
[![Greenkeeper badge](https://badges.greenkeeper.io/xiel/use-location-state.svg)](https://greenkeeper.io/)
[![codecov badge](https://img.shields.io/codecov/c/github/xiel/use-location-state/master.svg?color=hotpink)](https://codecov.io/gh/xiel/use-location-state)

@@ -15,7 +16,7 @@ ![GitHub top language](https://img.shields.io/github/languages/top/xiel/use-location-state.svg)

- makes it easy to share the application in a customizable state
- __`useLocationState(name, defaultValue)`__
- **`useLocationState(name, defaultValue)`**
- restores the latest value after navigation actions (back/forward), by keeping value in `history.state`
- supported value types: `string | number | boolean | Date | Array | Object`
- handles complex & nested values - all values that can be serialized are supported
- __`useQueryState(name, defaultValue)`__
- **`useQueryState(name, defaultValue)`**
- restores the latest value from URL (`location.href`) and after navigation actions (back/forward)

@@ -25,3 +26,2 @@ - supported value types: `string | number | boolean | Date | string[]`

- invalid entries from the query string are discarded and the component will receive the defaultValue instead

@@ -36,9 +36,9 @@ <img style="display: block; margin: auto;" src="https://repository-images.githubusercontent.com/182417896/058a9d00-e2e1-11e9-8467-8923219ec500" />

Using __`react-router`__ or another popular router? For the best experience install one of the [router integrations](#router-integration-optional).
Using **`react-router`** or another popular router? For the best experience install one of the [router integrations](#router-integration-optional).
## Usage
`useLocationState()` and `useQueryState()` work similar to the `useState()` [hook](https://reactjs.org/docs/hooks-overview.html#state-hook), as they also return the current value and a update function in a tuple `[currentValue, updateValueFn]`.
`useLocationState()` and `useQueryState()` work similar to the `useState()` [hook](https://reactjs.org/docs/hooks-overview.html#state-hook), as they also return the current value and a update function in a tuple `[currentValue, updateValueFn]`.
The *important difference* is that __you must pass a name__ before your __default value__ for your state.
The _important difference_ is that **you must pass a name** before your **default value** for your state.

@@ -63,2 +63,3 @@ ```javascript

```
The updated state will be restored when the pages reloads and after the user navigated to a new page and comes back using a back/forward action.

@@ -68,3 +69,3 @@

`useQueryState()` is a great, when you want to store information about the current state of you app in the URL.
`useQueryState()` is a great, when you want to store information about the current state of you app in the URL.

@@ -74,2 +75,3 @@ ```javascript

```
The name you pass will be used as a parameter name in the query string, when setting a new value:

@@ -80,2 +82,3 @@

```
After calling the update function `setValue()` with a new value, the state will be saved withing the query string of the browser, so that the new state is reproducable after reloads or history navigation (using forward / back button) or by loading the same URL anywhere else.

@@ -92,3 +95,3 @@

In cases where you want the updated state to be represented as a __new entry in the history__ you can pass a options object to the set function, with the method property set to `'push'`.
In cases where you want the updated state to be represented as a **new entry in the history** you can pass a options object to the set function, with the method property set to `'push'`.

@@ -102,2 +105,3 @@ ```javascript

### Example
```javascript

@@ -110,3 +114,5 @@ import { useQueryState } from 'use-location-state'

<div>
<button type="button" onClick={() => setActive(!active)}>Toggle</button>
<button type="button" onClick={() => setActive(!active)}>
Toggle
</button>
{active && <p>Some active content</p>}

@@ -117,2 +123,3 @@ </div>

```
<a href="https://codesandbox.io/embed/zqm4o19yrx">

@@ -122,3 +129,2 @@ <img width="150" alt="Example in CodeSandbox" src="https://codesandbox.io/static/img/play-codesandbox.svg">

### Example with multiple useQueryState hooks in one component

@@ -136,2 +142,3 @@

```
<a href="https://codesandbox.io/embed/github/xiel/use-location-state/tree/master/src/examples/use-location-state/?fontsize=14&module=%2Fsrc%2Fpages%2FQueryStateDemo.tsx">

@@ -145,3 +152,3 @@ <img width="150" alt="Example in CodeSandbox" src="https://codesandbox.io/static/img/play-codesandbox.svg">

We plan to provide clean and easy-to-use integrations for all popular routers.
We plan to provide clean and easy-to-use integrations for all popular routers.
At the moment we provide integrations for:

@@ -154,9 +161,13 @@

```
```javascript
import { useLocationState, useQueryState } from 'react-router-use-location-state'
```
Usage works the same as described above, except that the URL will look like this now:
```javascript
http://localhost:3000/?itemName=different+value
```
<a href="https://codesandbox.io/s/github/xiel/use-location-state/tree/master/src/examples/react-router-use-location-state?fontsize=14&module=%2Fsrc%2Fpages%2FQueryStateDemo.tsx">

@@ -166,2 +177,15 @@ <img width="150" alt="Edit react-router-use-location-state-example" src="https://codesandbox.io/static/img/play-codesandbox.svg">

### Gatsby & @reach/router
Gatsby & Reach Router are supported. Gatsby currently always scrolls up on location (state) changes. To keep the scroll position, when you update location state using the update function of `useLocationState`, add these lines to the **gatsby-browser.js** file in gatsby root folder.
```javascript
// keeps same scroll pos when history state is pushed/replaced (same location === same position)
// see: https://www.gatsbyjs.org/docs/browser-apis/#shouldUpdateScroll
exports.shouldUpdateScroll = ({ routerProps, getSavedScrollPosition }) => {
const currentPosition = getSavedScrollPosition(routerProps.location)
return currentPosition || true
}
```
### More routers soon - work in progress

@@ -176,4 +200,4 @@

```javascript
import 'react-app-polyfill/ie11';
import 'react-app-polyfill/stable';
import 'react-app-polyfill/ie11'
import 'react-app-polyfill/stable'
```
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc