import * as SecureStore from 'expo-secure-store' import { useCallback, useEffect, useReducer } from 'react' import { Platform } from 'react-native' type UseStateHook = [[boolean, T | null], (value: T | null) => void] function useAsyncState(initialValue: [boolean, T | null] = [true, null]): UseStateHook { return useReducer( (state: [boolean, T | null], action: T | null = null): [boolean, T | null] => [false, action], initialValue ) as UseStateHook } export async function setStorageItemAsync(key: string, value: string | null) { if (Platform.OS === 'web') { try { if (value === null) { localStorage.removeItem(key) } else { localStorage.setItem(key, value) } } catch (e) { console.error('Local storage is unavailable:', e) } } else { if (value == null) { await SecureStore.deleteItemAsync(key) } else { await SecureStore.setItemAsync(key, value) } } } export function useStorageState(key: string): UseStateHook { // Public const [state, setState] = useAsyncState() // Get useEffect(() => { if (Platform.OS === 'web') { try { if (typeof localStorage !== 'undefined') { setState(localStorage.getItem(key)) } } catch (e) { console.error('Local storage is unavailable:', e) } } else { SecureStore.getItemAsync(key).then((value) => { setState(value) }) } }, [key, setState]) // Set const setValue = useCallback( (value: string | null) => { setState(value) setStorageItemAsync(key, value) }, [key, setState] ) return [state, setValue] }