15. AsyncStorage и хранение данных
Для локального хранения данных в React Native есть несколько опций — от простого AsyncStorage до зашифрованного Secure Store.
AsyncStorage
Заголовок раздела «AsyncStorage»Простое key-value хранилище (как localStorage, но асинхронное):
npx expo install @react-native-async-storage/async-storageimport AsyncStorage from '@react-native-async-storage/async-storage';
// Сохранитьawait AsyncStorage.setItem('user', JSON.stringify({ name: 'Яша', age: 1 }));
// Получитьconst raw = await AsyncStorage.getItem('user');const user = raw ? JSON.parse(raw) : null;
// Удалитьawait AsyncStorage.removeItem('user');
// Все ключиconst keys = await AsyncStorage.getAllKeys();
// Очистить всёawait AsyncStorage.clear();
// Batch операцииawait AsyncStorage.multiSet([['key1', 'val1'], ['key2', 'val2']]);MMKV — быстрее AsyncStorage в 30x
Заголовок раздела «MMKV — быстрее AsyncStorage в 30x»npx expo install react-native-mmkvimport { MMKV } from 'react-native-mmkv';
const storage = new MMKV();
// Синхронное API (не нужен await!)storage.set('user.name', 'Яша');storage.set('count', 42);storage.set('active', true);
const name = storage.getString('user.name'); // 'Яша'const count = storage.getNumber('count'); // 42storage.delete('user.name');Expo SecureStore — зашифрованное хранилище
Заголовок раздела «Expo SecureStore — зашифрованное хранилище»Для токенов, паролей, ключей. iOS Keychain / Android Keystore:
npx expo install expo-secure-storeimport * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('token', 'eyJhbGciOiJIUzI1NiJ9...');const token = await SecureStore.getItemAsync('token');await SecureStore.deleteItemAsync('token');Zustand + AsyncStorage (персистентный стейт)
Заголовок раздела «Zustand + AsyncStorage (персистентный стейт)»import { create } from 'zustand';import { persist, createJSONStorage } from 'zustand/middleware';import AsyncStorage from '@react-native-async-storage/async-storage';
const useUserStore = create( persist( (set) => ({ user: null, setUser: (user) => set({ user }), logout: () => set({ user: null }), }), { name: 'user-storage', storage: createJSONStorage(() => AsyncStorage), } ));Custom hook для хранения
Заголовок раздела «Custom hook для хранения»function useStorage<T>(key: string, defaultValue: T) { const [value, setValue] = useState<T>(defaultValue); const [loading, setLoading] = useState(true);
useEffect(() => { AsyncStorage.getItem(key).then(raw => { if (raw) setValue(JSON.parse(raw)); setLoading(false); }); }, [key]);
const save = async (newValue: T) => { setValue(newValue); await AsyncStorage.setItem(key, JSON.stringify(newValue)); };
return { value, save, loading };}
// Использованиеconst { value: theme, save: saveTheme } = useStorage('theme', 'dark');