From 5f4611d65e40eae3ca6191a15f68d69ea5a1c4cb Mon Sep 17 00:00:00 2001 From: Kirill Rogovoy Date: Tue, 20 Jul 2021 21:24:52 +0300 Subject: WIP --- util/persistant-state.ts | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 util/persistant-state.ts (limited to 'util') 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( + storageKey: string, + defaultValue: V, + options: { + storage?: Storage + } = {}, +): [V, (v: V | ((v: V) => V)) => void] { + const storage = getStorage(storageKey, options.storage ?? localStorage) + + const storageValue = storage.get() + const calculatedDefaultValue = storageValue !== undefined ? storageValue : defaultValue + if (calculatedDefaultValue !== storageValue) { + storage.update(calculatedDefaultValue) + } + + const [value, setValue] = useState(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(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) + }, + } +} -- cgit v1.2.3