Skip to content

Instantly share code, notes, and snippets.

@KristofferEriksson
Last active July 25, 2024 19:33
Show Gist options
  • Save KristofferEriksson/4a948a1572f5eb7907c3430b58845a9a to your computer and use it in GitHub Desktop.
Save KristofferEriksson/4a948a1572f5eb7907c3430b58845a9a to your computer and use it in GitHub Desktop.
An easy-to-use API for storing and retrieving data from Local Storage in React, with built-in real-time synchronization
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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment