JAVASCRIPT
Persist State with `useLocalStorage` React Hook
Create a `useLocalStorage` hook to effortlessly synchronize and persist React state with the browser's local storage, ensuring data remains available across page reloads.
import { useState, useEffect, useCallback } from 'react';
function useLocalStorage(key, initialValue) {
const readValue = useCallback(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.warn(`Error reading localStorage key "${key}":`, error);
return initialValue;
}
}, [key, initialValue]);
const [storedValue, setStoredValue] = useState(readValue);
const setValue = useCallback((value) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.warn(`Error setting localStorage key "${key}":`, error);
}
}, [key, storedValue]);
useEffect(() => {
setStoredValue(readValue());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // Only run once on mount to handle initial value correctly
return [storedValue, setValue];
}
// Example Usage:
/*
function ThemeSwitcher() {
const [theme, setTheme] = useLocalStorage('app-theme', 'light');
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<div>
<p>Current Theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
*/
How it works: The `useLocalStorage` hook initializes state from `localStorage` on component mount and automatically updates `localStorage` whenever the state changes. It takes a `key` and an `initialValue`. The `useState` is initialized using a `readValue` function to parse the stored JSON or use the `initialValue`. The `setValue` function updates both the React state and `localStorage`, handling function-based state updates. This provides a seamless way to persist small pieces of data across user sessions.