aboutsummaryrefslogtreecommitdiff
path: root/packages/web-util/src/hooks/useLocalStorage.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web-util/src/hooks/useLocalStorage.ts')
-rw-r--r--packages/web-util/src/hooks/useLocalStorage.ts64
1 files changed, 47 insertions, 17 deletions
diff --git a/packages/web-util/src/hooks/useLocalStorage.ts b/packages/web-util/src/hooks/useLocalStorage.ts
index 131825736..55efd01cb 100644
--- a/packages/web-util/src/hooks/useLocalStorage.ts
+++ b/packages/web-util/src/hooks/useLocalStorage.ts
@@ -19,6 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { Codec } from "@gnu-taler/taler-util";
import { useEffect, useState } from "preact/hooks";
import {
ObservableMap,
@@ -27,9 +28,9 @@ import {
memoryMap,
} from "../utils/observable.js";
-export interface LocalStorageState {
- value?: string;
- update: (s: string) => void;
+export interface LocalStorageState<Type = string> {
+ value?: Type;
+ update: (s: Type) => void;
reset: () => void;
}
@@ -47,33 +48,62 @@ const storage: ObservableMap<string, string> = (function buildStorage() {
}
})();
-export function useLocalStorage(
+//with initial value
+export function useLocalStorage<Type = string>(
key: string,
- initialValue: string,
-): Required<LocalStorageState>;
-export function useLocalStorage(key: string): LocalStorageState;
-export function useLocalStorage(
+ options?: {
+ defaultValue: Type;
+ codec?: Codec<Type>;
+ },
+): Required<LocalStorageState<Type>>;
+//without initial value
+export function useLocalStorage<Type = string>(
key: string,
- initialValue?: string,
-): LocalStorageState {
- const [storedValue, setStoredValue] = useState<string | undefined>(
- (): string | undefined => {
- return storage.get(key) ?? initialValue;
+ options?: {
+ codec?: Codec<Type>;
+ },
+): LocalStorageState<Type>;
+// impl
+export function useLocalStorage<Type = string>(
+ key: string,
+ options?: {
+ defaultValue?: Type;
+ codec?: Codec<Type>;
+ },
+): LocalStorageState<Type> {
+ function convert(updated: string | undefined): Type | undefined {
+ if (updated === undefined) return options?.defaultValue; //optional
+ try {
+ return !options?.codec
+ ? (updated as Type)
+ : options.codec.decode(JSON.parse(updated));
+ } catch (e) {
+ //decode error
+ return options?.defaultValue;
+ }
+ }
+ const [storedValue, setStoredValue] = useState<Type | undefined>(
+ (): Type | undefined => {
+ const prev = storage.get(key);
+ return convert(prev);
},
);
useEffect(() => {
return storage.onUpdate(key, () => {
const newValue = storage.get(key);
- setStoredValue(newValue ?? initialValue);
+ setStoredValue(convert(newValue));
});
}, []);
- const setValue = (value?: string): void => {
+ const setValue = (value?: Type): void => {
if (value === undefined) {
storage.delete(key);
} else {
- storage.set(key, value);
+ storage.set(
+ key,
+ options?.codec ? JSON.stringify(value) : (value as string),
+ );
}
};
@@ -81,7 +111,7 @@ export function useLocalStorage(
value: storedValue,
update: setValue,
reset: () => {
- setValue(initialValue);
+ setValue(options?.defaultValue);
},
};
}