JAVASCRIPT
Persisting React State with `useLocalStorage` Custom Hook
Build a `useLocalStorage` custom hook to automatically synchronize a React component's state with the browser's local storage, preserving data across sessions.
import { useState, useEffect } from 'react';
/**
* Custom hook to manage state that persists in localStorage.
* @param {string} key The key for localStorage.
* @param {any} initialValue The initial value for the state.
* @returns {[any, Function]} A tuple containing the state value and its setter.
*/
export function useLocalStorage(key, initialValue) {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
// useEffect to update localStorage when the state changes
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch (error) {
console.error(error);
}
}, [key, storedValue]); // Only re-run if key or storedValue changes
return [storedValue, setStoredValue];
}
// Example Usage:
// function UserSettings() {
// const [theme, setTheme] = useLocalStorage('appTheme', 'light');
// const [username, setUsername] = useLocalStorage('userName', '');
// return (
// <div>
// <p>Theme: {theme}</p>
// <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
// Toggle Theme
// </button>
// <p>Username: {username}</p>
// <input
// type="text"
// value={username}
// onChange={(e) => setUsername(e.target.value)}
// placeholder="Enter username"
// />
// </div>
// );
// }
How it works: The `useLocalStorage` custom hook provides a convenient way to synchronize a React component's state with the browser's `localStorage`. When the component mounts, it attempts to load the stored value; otherwise, it uses an `initialValue`. Any subsequent changes to the state automatically update `localStorage` via a `useEffect` hook. This ensures that data persists across browser sessions, enhancing user experience without requiring a backend.