use-local-storage-state
Advanced tools
Comparing version 6.0.1 to 6.0.2
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createLocalStorageStateHook = void 0; | ||
const react_1 = require("react"); | ||
/** | ||
* A wrapper for `JSON.parse()` which supports the return value of `JSON.stringify(undefined)` | ||
* which returns the string `"undefined"` and this method returns the value `undefined`. | ||
*/ | ||
function parseJSON(value) { | ||
return value === 'undefined' | ||
? undefined | ||
: | ||
: // JSON.parse() doesn't accept non-string values, this is why we pass empty | ||
// string which will throw an error which can be handled | ||
JSON.parse(value !== null && value !== void 0 ? value : ''); | ||
} | ||
/** | ||
* Abstraction for localStorage that uses an in-memory fallback when localStorage throws an error. | ||
* Reasons for throwing an error: | ||
* - maximum quota is exceeded | ||
* - under Mobile Safari (since iOS 5) when the user enters private mode `localStorage.setItem()` | ||
* will throw | ||
* - trying to access localStorage object when cookies are disabled in Safari throws | ||
* "SecurityError: The operation is insecure." | ||
*/ | ||
const data = {}; | ||
@@ -40,4 +55,10 @@ const storage = { | ||
}; | ||
/** | ||
* Used to track usages of `useLocalStorageState()` with identical `key` values. If we encounter | ||
* duplicates we throw an error to the user telling them to use `createLocalStorageStateHook` | ||
* instead. | ||
*/ | ||
const initializedStorageKeys = new Set(); | ||
function useLocalStorageState(key, defaultValue) { | ||
// we don't support updating the `defaultValue` the same way `useState()` doesn't support it | ||
const [defaultValueState] = react_1.useState(() => { | ||
@@ -47,6 +68,11 @@ const isCallable = (value) => typeof value === 'function'; | ||
}); | ||
const [state, setState] = react_1.useState(() => { | ||
const getDefaultState = react_1.useCallback(() => { | ||
return { | ||
value: storage.get(key, defaultValueState), | ||
isPersistent: (() => { | ||
/** | ||
* We want to return `true` on the server. If you render a message based on `isPersistent` and the | ||
* server returns `false` then the message will flicker until hydration is done: | ||
* `{!isPersistent && <span>You changes aren't being persisted.</span>}` | ||
*/ | ||
if (typeof window === 'undefined') { | ||
@@ -65,3 +91,4 @@ return true; | ||
}; | ||
}); | ||
}, [defaultValueState, key]); | ||
const [state, setState] = react_1.useState(getDefaultState); | ||
const updateValue = react_1.useMemo(() => { | ||
@@ -92,2 +119,5 @@ const fn = (newValue) => { | ||
}, [key, defaultValueState]); | ||
/** | ||
* Detects incorrect usage of the library and throws an error with a suggestion how to fix it. | ||
*/ | ||
react_1.useEffect(() => { | ||
@@ -105,2 +135,5 @@ if (initializedStorageKeys.has(key)) { | ||
}, []); | ||
/** | ||
* Syncs changes across tabs and iframe's. | ||
*/ | ||
react_1.useEffect(() => { | ||
@@ -118,2 +151,13 @@ const onStorage = (e) => { | ||
}, [defaultValueState]); | ||
/** | ||
* Update the state when the `key` property changes. | ||
*/ | ||
const isFirstRender = react_1.useRef(true); | ||
react_1.useEffect(() => { | ||
if (isFirstRender.current) { | ||
isFirstRender.current = false; | ||
return; | ||
} | ||
setState(getDefaultState()); | ||
}, [getDefaultState]); | ||
return [state.value, updateValue, state.isPersistent]; | ||
@@ -120,0 +164,0 @@ } |
{ | ||
"name": "use-local-storage-state", | ||
"version": "6.0.1", | ||
"version": "6.0.2", | ||
"description": "React hook that persist data in local storage. Done right.", | ||
@@ -32,3 +32,3 @@ "license": "MIT", | ||
"release": "yarn run build && np", | ||
"prettier": "prettier --write --config .prettierrc.yaml *.ts" | ||
"prettier": "prettier --write --config .prettierrc.yaml {*.ts,*.json}" | ||
}, | ||
@@ -57,4 +57,4 @@ "engines": { | ||
"ts-jest": "^25.2.1", | ||
"typescript": "^3.8.3" | ||
"typescript": "^4.1.3" | ||
} | ||
} |
15760
196