useLocalStorage
import { useEffect, useState } from "react";
function useLocalStorage() {
const [loadingStates, setLoadingStates] = useState<Map<string, boolean>>(
new Map()
);
const setStorageValue = <T>(key: string, value: T) => {
try {
window.localStorage.setItem(key, JSON.stringify(value));
window.dispatchEvent(new Event("storage"));
} catch (error) {
console.error(`Error setting localStorage key "${key}":`, error);
}
};
const getStorageValue = <T>(
key: string,
fallbackValue?: T
): [T | undefined, boolean] => {
const [value, setStorageValue] = useState<T | undefined>(fallbackValue);
const [isLoading, setIsLoading] = useState<boolean>(true);
useEffect(() => {
setIsLoading(loadingStates.get(key) ?? true);
try {
const item = window.localStorage.getItem(key);
setStorageValue(item !== null ? JSON.parse(item) : fallbackValue);
} catch (error) {
console.error(error);
setStorageValue(fallbackValue);
} finally {
setIsLoading(false);
setLoadingStates((prev) => new Map(prev).set(key, false));
}
}, [key, fallbackValue, loadingStates]);
return [value, isLoading];
};
// Effect to update component when localStorage changes
useEffect(() => {
const handleStorageChange = (event: StorageEvent) => {
if (event.key) {
setLoadingStates((prev) =>
new Map(prev).set(event.key as string, true)
);
}
};
window.addEventListener("storage", handleStorageChange);
return () => {
window.removeEventListener("storage", handleStorageChange);
};
}, []);
return { getStorageValue, setStorageValue };
}
export default useLocalStorage;