import React from 'react' import { getLocalStorageItem, removeLocalStorageItem, setLocalStorageItem } from 'utils' const useLocalStorageSubscribe = (callback: () => void) => { window.addEventListener('storage', callback) return () => window.removeEventListener('storage', callback) } export function useLocalStorage( key: string, initialValue: T ): [T, React.Dispatch>] { const getSnapshot = () => getLocalStorageItem(key, initialValue) const data = React.useSyncExternalStore(useLocalStorageSubscribe, getSnapshot) const setState: React.Dispatch> = React.useCallback( (v: React.SetStateAction) => { try { const nextState = typeof v === 'function' ? (v as (prevState: T) => T)(JSON.parse(data)) : v if (nextState === undefined || nextState === null) { removeLocalStorageItem(key) } else { setLocalStorageItem(key, JSON.stringify(nextState)) } } catch (e) { console.warn(e) } }, [key, data] ) React.useEffect(() => { // Set local storage only when it's empty const data = window.localStorage.getItem(key) if (data === null) { setLocalStorageItem(key, JSON.stringify(initialValue)) } }, [key, initialValue]) return [JSON.parse(data) as T, setState] }