localStorage, and a function to update it.useState() hook to initialize the value to defaultValue.useRef() hook to create a ref that will hold the name of the value in localStorage.useEffect() hook for initialization, value change and name change respectively.Storage.getItem() to update value if there's a stored value or Storage.setItem() to persist the current value.value is updated, use Storage.setItem() to store the new value.name is updated, use Storage.setItem() to create the new key, update the nameRef and use Storage.removeItem() to remove the previous key from localStorage.localStorage due to other code. Both of these issues can be easily handled (e.g. JSON serialization and handling the 'storage' event).const usePersistedState = (name, defaultValue) => {
const [value, setValue] = React.useState(defaultValue);
const nameRef = React.useRef(name);
React.useEffect(() => {
try {
const storedValue = localStorage.getItem(name);
if (storedValue !== null) setValue(storedValue);
else localStorage.setItem(name, defaultValue);
} catch {
setValue(defaultValue);
}
}, []);
React.useEffect(() => {
try {
localStorage.setItem(nameRef.current, value);
} catch {}
}, [value]);
React.useEffect(() => {
const lastName = nameRef.current;
if (name !== lastName) {
try {
localStorage.setItem(name, value);
nameRef.current = name;
localStorage.removeItem(lastName);
} catch {}
}
}, [name]);
return [value, setValue];
};
const MyComponent = ({ name }) => {
const [val, setVal] = usePersistedState(name, 10);
return (
<input
value={val}
onChange={e => {
setVal(e.target.value);
}}
/>
);
};
const MyApp = () => {
const [name, setName] = React.useState('my-value');
return (
<>
<MyComponent name={name} />
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</>
);
};
ReactDOM.render(<MyApp />, document.getElementById('root'));Subscribe to get resources directly to your inbox. You won't receive any spam! ✌️