-
-
Save turdiyev/76cb130db5910d0b57c67b84f582b9c5 to your computer and use it in GitHub Desktop.
React Hook recipe from https://usehooks.com. Demo: https://codesandbox.io/s/qxkr4mplv6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect } from 'react'; | |
// Usage | |
function App() { | |
// Similar to useState but we pass in a key to value in local storage | |
// With useState: const [name, setName] = useState('Bob'); | |
const [name, setName] = useLocalStorage('name', 'Bob'); | |
return ( | |
<div> | |
<input | |
type="text" | |
placeholder="Enter your name" | |
value={name} | |
onChange={e => setName(e.target.value)} | |
/> | |
</div> | |
); | |
} | |
// Hook | |
function useLocalStorage(key, initialValue) { | |
// The initialValue arg is only used if there is nothing in localStorage ... | |
// ... otherwise we use the value in localStorage so state persist through a page refresh. | |
// We pass a function to useState so localStorage lookup only happens once. | |
// We wrap in try/catch in case localStorage is unavailable | |
const [item, setInnerValue] = useState(() => { | |
try { | |
return window.localStorage.getItem(key) | |
? JSON.parse(window.localStorage.getItem(key)) | |
: initialValue; | |
} catch (error) { | |
// Return default value if JSON parsing fails | |
return initialValue; | |
} | |
}); | |
// Return a wrapped version of useState's setter function that ... | |
// ... persists the new value to localStorage. | |
const setValue = value => { | |
setInnerValue(value); | |
window.localStorage.setItem(key, JSON.stringify(item)); | |
}; | |
// Alternatively we could update localStorage inside useEffect ... | |
// ... but this would run every render and it really only needs ... | |
// ... to happen when the returned setValue function is called. | |
/* | |
useEffect(() => { | |
window.localStorage.setItem(key, JSON.stringify(item)); | |
}); | |
*/ | |
return [item, setValue]; | |
} |
BTW, If you need typescript code, here you are:
import { useState, Dispatch, SetStateAction } from 'react';
export default function <S>(
key: string,
initialValue?: S
): [S, Dispatch<SetStateAction<S>>] {
// The initialValue arg is only used if there is nothing in localStorage ...
// ... otherwise we use the value in localStorage so state persist through a page refresh.
// We pass a function to useState so localStorage lookup only happens once.
// We wrap in try/catch in case localStorage is unavailable
const [item, setInnerValue] = useState<S>(() => {
try {
const valueItem = window.localStorage.getItem(key);
return valueItem ? JSON.parse(valueItem) : initialValue;
} catch (error) {
// Return default value if JSON parsing fails
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = (value: SetStateAction<S>): SetStateAction<S> => {
setInnerValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
return value;
};
// Alternatively we could update localStorage inside useEffect ...
// ... but this would run every render and it really only needs ...
// ... to happen when the returned setValue function is called.
/*
useEffect(() => {
window.localStorage.setItem(key, JSON.stringify(item));
});
*/
return [item, setValue];
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think and in my experience,
item
should bevalue
that inside ofJSON.stringify
: