Apr 24, 2024
useLocalStorage hook
Manage localStorage data realtime in React.
Hook to use local storage as a realtime data store in React. Utilizes the storage
event to listen for changes in local storage and update the react state accordingly.
import { Dispatch, SetStateAction, useState } from "react";
/**
* synchronie reactive state with local storage listener.
* @template T The type of the state value.
* @param {string} key The key under which the state will be stored in local storage.
* @param {T} initialValue The initial value of the state.
* @returns {[T, Dispatch<SetStateAction<T>>]} An array containing the current state value and a function to update that value.
*/
export function useLocalStorage<T>(key: string, initialValue: T): [T, Dispatch<SetStateAction<T>>] {
const [state, setState] = useState(initialValue);
useEffect(() => {
// Initialize the state
try {
const value = window.localStorage.getItem(key);
// Check if the local storage already has any values,
// otherwise initialize it with the passed initialValue
const valueToStore = value ? JSON.parse(value) : initialValue;
setState(valueToStore);
} catch (error) {
console.error(error);
}
}, []);
useEffect(() => {
window.addEventListener("storage", () => {
try {
const value = window.localStorage.getItem(key);
// Check if the local storage already has any values,
// otherwise initialize it with the passed initialValue
const valueToStore = value ? JSON.parse(value) : initialValue;
setState(valueToStore);
} catch (error) {
console.error(error);
}
});
}, []);
/**
* Function to set a new value for the state, updating both the state and local storage.
* @param {T | SetStateAction<T>} value The new value for the state, or a function that returns the new value.
*/
const setValue = (value: T | SetStateAction<T>) => {
try {
// If the passed value is a callback function,
// then call it with the existing state.
const valueToStore = value instanceof Function ? value(state) : value;
window.localStorage.setItem(key, JSON.stringify(valueToStore));
window.dispatchEvent(new Event("storage"));
setState(value);
} catch (error) {
console.error(error);
}
};
return [state, setValue];
}