@har4s/use-local-storage
Version:
A React Hook for using Browser Local/Session Storage
86 lines (71 loc) • 2.27 kB
text/typescript
import { Dispatch, SetStateAction, useState } from "react";
export interface UseLocalStorageOptions {
persistent?: boolean;
}
export type UseLocalStorage<T> = [T, Dispatch<SetStateAction<T>>];
export default function useLocalStorage<T>(
key: string,
initialValue: SetStateAction<T>,
options?: UseLocalStorageOptions
): UseLocalStorage<T> {
const SSR = typeof window === "undefined";
let isPersistent = true;
if (!!options && typeof options.persistent !== "undefined") {
isPersistent = options.persistent;
}
let storage: Storage;
if (!SSR && !isPersistent) {
storage = sessionStorage;
} else if (!SSR) {
storage = localStorage;
}
const saveToStorage = (valueToStore: T) => {
try {
if (SSR) {
} else if (typeof valueToStore === "string") {
storage.setItem(key, valueToStore);
} else if (typeof valueToStore === "undefined") {
storage.setItem(key, "");
} else {
storage.setItem(key, JSON.stringify(valueToStore));
}
} catch {
console.warn(`Could not save ${key} to localStorage`);
}
};
function getValue(value: T, initOrCb: SetStateAction<T>): T {
if (initOrCb instanceof Function) {
const newValue = initOrCb(value);
saveToStorage(newValue);
return newValue;
}
return value ?? initOrCb;
}
const [storedValue, setStoredValue] = useState<T>(() => {
if (SSR) return getValue(null, initialValue);
let result: T;
const item = storage.getItem(key);
if (item === null) {
return getValue(null, initialValue);
}
try {
const parsed = JSON.parse(item);
if (!parsed) {
throw new Error("Empty value");
}
result = parsed;
} catch {
// Casting to T (which should resolve to string) because JSON.parse would
// throw an error if "foo" was passed, but properly casting "true" or "1"
// to their respective types
result = item as unknown as T;
}
return getValue(result, initialValue);
});
const setValue = (value: SetStateAction<T>) => {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
saveToStorage(valueToStore);
};
return [storedValue, setValue];
}