Skip to content

Instantly share code, notes, and snippets.

@Joehoel
Created February 6, 2026 08:30
Show Gist options
  • Select an option

  • Save Joehoel/37f09e8d7b7ad754fc00a5f1b5a32acc to your computer and use it in GitHub Desktop.

Select an option

Save Joehoel/37f09e8d7b7ad754fc00a5f1b5a32acc to your computer and use it in GitHub Desktop.
Secure Store
/**
* Async secure storage hook with loading state.
* Based on Expo's useStorageState pattern from expo-router examples.
* @see https://github.com/expo/expo/blob/main/apps/router-e2e/__e2e__/auth/useStorageState.ts
*/
import * as SecureStore from 'expo-secure-store';
import { useCallback, useEffect, useReducer } from 'react';
type SecureState<T> = [isLoading: boolean, value: T | null];
type SecureStateAction<T> = { type: 'loaded'; value: T | null } | { type: 'set'; value: T | null };
function createReducer<T>() {
return (state: SecureState<T>, action: SecureStateAction<T>): SecureState<T> => {
switch (action.type) {
case 'loaded':
return [false, action.value];
case 'set':
return [false, action.value];
}
};
}
interface UseSecureStateOptions {
json?: boolean;
}
export function useSecureState<T = string>(
key: string,
options?: UseSecureStateOptions
): [state: SecureState<T>, setValue: (value: T | null) => void] {
const isJson = options?.json ?? false;
const [state, dispatch] = useReducer(createReducer<T>(), [true, null]);
useEffect(() => {
SecureStore.getItemAsync(key).then((stored) => {
if (stored === null) {
dispatch({ type: 'loaded', value: null });
} else {
const value = isJson ? JSON.parse(stored) : stored;
dispatch({ type: 'loaded', value });
}
});
}, [key, isJson]);
const setValue = useCallback(
(value: T | null) => {
dispatch({ type: 'set', value });
if (value === null) {
SecureStore.deleteItemAsync(key);
} else {
const toStore = isJson ? JSON.stringify(value) : (value as string);
SecureStore.setItemAsync(key, toStore);
}
},
[key, isJson]
);
return [state, setValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment