Last active
August 3, 2022 18:04
-
-
Save tilap/0e0895093da13a673200311cad58f090 to your computer and use it in GitHub Desktop.
Use and sync a localStorage entry with react hook
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 { useCallback, useEffect, useState, useMemo } from 'react'; | |
const isBrowser = typeof window !== 'undefined'; | |
const isLocalstorageAvailable = () => { | |
if (!isBrowser) { | |
return false; | |
} | |
const test = `test-${Date.now()}`; | |
try { | |
localStorage.setItem(test, test); | |
localStorage.removeItem(test); | |
return true; | |
} catch (e) { | |
return false; | |
} | |
}; | |
// React hook | |
const useLocalstorage = (key, initialValue = '') => { | |
const available = isLocalstorageAvailable(); | |
const getValueFromLocalstorage = useCallback(() => { | |
try { | |
if (!available) { | |
return initialValue; | |
} | |
const item = localStorage.getItem(key); | |
return item ? JSON.parse(item) : initialValue; | |
} catch (error) { | |
return initialValue; | |
} | |
}, [available, initialValue, key]); | |
const [storedValue, setStoredValue] = useState(getValueFromLocalstorage()); | |
useEffect(() => { | |
const value = getValueFromLocalstorage(); | |
setStoredValue(value); | |
}, [available, getValueFromLocalstorage]); | |
// Listen to localstorage change to apply it | |
const changeHandler = useCallback( | |
e => { | |
const { key: changeKey, newValue } = e; | |
if (key === changeKey) { | |
setStoredValue(JSON.parse(newValue)); | |
} | |
}, | |
[key] | |
); | |
// Listen changes | |
useEffect(() => { | |
if (available) { | |
window.addEventListener('storage', changeHandler); | |
return () => { | |
window.removeEventListener('storage', changeHandler); | |
}; | |
} | |
}, [available]); // eslint-disable-line react-hooks/exhaustive-deps | |
// Build the output | |
return useMemo(() => { | |
const setValue = value => { | |
if (!available) { | |
return false; | |
} | |
const valueToStore = value instanceof Function ? value(storedValue) : value; | |
if (valueToStore !== storedValue) { | |
setStoredValue(valueToStore); | |
window.localStorage.setItem(key, JSON.stringify(valueToStore)); | |
} | |
}; | |
return [storedValue, setValue]; | |
}, [storedValue, available, key]); | |
}; | |
export default useLocalstorage; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment