diff options
author | Kirill Rogovoy <[email protected]> | 2021-07-20 21:24:52 +0300 |
---|---|---|
committer | Kirill Rogovoy <[email protected]> | 2021-07-20 21:24:52 +0300 |
commit | 5f4611d65e40eae3ca6191a15f68d69ea5a1c4cb (patch) | |
tree | 273dfc086444533d86d580961c92ba8d14781a67 /util/persistant-state.ts | |
parent | f0bf4e7afdcd8b02a62be45ab3e7d047ed865a79 (diff) |
WIP
Diffstat (limited to 'util/persistant-state.ts')
-rw-r--r-- | util/persistant-state.ts | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/util/persistant-state.ts b/util/persistant-state.ts new file mode 100644 index 0000000..5e7e35e --- /dev/null +++ b/util/persistant-state.ts @@ -0,0 +1,59 @@ +import { useState, useEffect } from 'react' + +export function usePersistantState<V>( + storageKey: string, + defaultValue: V, + options: { + storage?: Storage + } = {}, +): [V, (v: V | ((v: V) => V)) => void] { + const storage = getStorage<V | undefined>(storageKey, options.storage ?? localStorage) + + const storageValue = storage.get() + const calculatedDefaultValue = storageValue !== undefined ? storageValue : defaultValue + if (calculatedDefaultValue !== storageValue) { + storage.update(calculatedDefaultValue) + } + + const [value, setValue] = useState<V>(calculatedDefaultValue) + + // change state gracefully when changing the storageKey + useEffect(() => { + if (value !== calculatedDefaultValue) { + setValue(calculatedDefaultValue) + } + }, [storageKey]) + const set = (newValueOrFn: V | ((v: V) => V)) => { + if (newValueOrFn instanceof Function) { + setValue((oldValue) => { + const newValue = newValueOrFn(oldValue) + storage.update(newValue) + return newValue + }) + return + } + setValue(newValueOrFn) + storage.update(newValueOrFn) + } + + return [value, set] +} + +export function getStorage<T>(key: string, storage: Storage) { + return { + get(): T | undefined { + const value = storage.getItem(key) + if (value && value !== 'undefined') { + return JSON.parse(value) + } + + return undefined + }, + update(updatedState: T) { + storage.setItem(key, JSON.stringify(updatedState)) + }, + remove() { + storage.removeItem(key) + }, + } +} |