Storage and Secure Data
Persistence options from simple key-value to secure tokens and local files/databases.
Busque em todas as páginas da documentação
Persistence options from simple key-value to secure tokens and local files/databases.
Unencrypted key-value storage for preferences and non-secret caches. Prefer @react-native-async-storage/async-storage (Expo-compatible).
import AsyncStorage from "@react-native-async-storage/async-storage";
await AsyncStorage.setItem("theme", "dark");
const theme = await AsyncStorage.getItem("theme");Batch reads/writes to reduce bridge round-trips.
await AsyncStorage.multiSet([
["onboarding.done", "1"],
["locale", "en"],
]);
const pairs = await AsyncStorage.multiGet(["onboarding.done", "locale"]);Store secrets (session tokens, refresh tokens) in the platform keychain/keystore via expo-secure-store.
import * as SecureStore from "expo-secure-store";
await SecureStore.setItemAsync("accessToken", token);
const token = await SecureStore.getItemAsync("accessToken");Clear credentials on logout.
await SecureStore.deleteItemAsync("accessToken");
await SecureStore.deleteItemAsync("refreshToken");App document directory paths for durable user files with expo-file-system.
import * as FileSystem from "expo-file-system";
const dir = FileSystem.documentDirectory; // string | null
const path = `${dir}notes.txt`;Simple text file IO for exports and offline drafts.
await FileSystem.writeAsStringAsync(path, contents, {
encoding: FileSystem.EncodingType.UTF8,
});
const text = await FileSystem.readAsStringAsync(path);Put disposable downloads in the cache directory so the OS may reclaim space.
const cachePath = `${FileSystem.cacheDirectory}avatar-tmp.jpg`;Local relational storage with expo-sqlite for structured offline data.
import * as SQLite from "expo-sqlite";
const db = await SQLite.openDatabaseAsync("app.db");
await db.execAsync("CREATE TABLE IF NOT EXISTS notes (id TEXT PRIMARY KEY, body TEXT);");MMKV (community module) is a fast synchronous key-value store often used with Zustand. Requires native code - fine in dev builds; not pure Expo Go unless supported by your workflow.
// Conceptual: storage.set("key", value); const v = storage.getString("key");Sketch of persisting a slice - wire your storage engine in persist middleware.
// persist( (set) => ({ token: null, setToken: (t) => set({ token: t }) }),
// { name: "auth", storage: createJSONStorage(() => asyncStorage) } )Namespace user keys and wipe them on logout so the next account never sees stale data.
async function clearUserData() {
await AsyncStorage.multiRemove(["user.profile", "user.prefs"]);
await SecureStore.deleteItemAsync("accessToken");
}Stored JSON can be corrupt - parse behind try/catch and fall back to defaults.
function readJson<T>(raw: string | null, fallback: T): T {
if (!raw) return fallback;
try {
return JSON.parse(raw) as T;
} catch {
return fallback;
}
}Keep a schema version next to persisted state and run migrations when it changes.
const VERSION = "2";
const v = await AsyncStorage.getItem("storage.version");
if (v !== VERSION) {
await migrate(v);
await AsyncStorage.setItem("storage.version", VERSION);
}Generate opaque ids with expo-crypto instead of weak Math.random.
import * as Crypto from "expo-crypto";
const id = Crypto.randomUUID();SecureStore can fail on restricted devices - catch errors and degrade gracefully (re-auth, in-memory session).
try {
await SecureStore.setItemAsync("accessToken", token);
} catch {
// Fall back: keep token in memory only for this session
memorySession.token = token;
}Stack versions: React 19.2.3 · React Native 0.86.0 · Expo SDK 57
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026