ReadyNative

AsyncStorage

Set up AsyncStorage for storage in an Expo app with ReadyNative: async-only key/value, the community standard · Expo Go OK

Expo Go: yes

Runs in Expo Go; no dev build needed for this module.

AsyncStorage is the community-standard async key/value store (@react-native-async-storage/async-storage), behind the same src/lib/storage.ts. I'd pick it for one reason: a library you depend on hard-requires AsyncStorage - some auth and analytics SDKs take it as a storage option, and this way you keep a single store. Otherwise prefer kv-store (Expo Go and sync reads on native) or mmkv (fastest, dev build). Callers don't change: they import storage from @/lib/storage.

Setup

bun run setup --storage async-storage

That's it - setup writes src/lib/storage.ts (createAsyncStorageStorage() plus the active storage, with no *Sync methods), adds @react-native-async-storage/async-storage 2.2.0 (the SDK 57 pin), a jest stand-in under __mocks__/ that re-exports the package's own jest/async-storage-mock, and an adapter test. There's no config plugin.

Usage

import { storage } from "@/lib/storage";

await storage.setItem("readynative:draft", JSON.stringify(draft));
const raw = await storage.getItem("readynative:draft");
storage.getItemSync; // undefined - always await getItem()

If a SDK wants the raw module, pass AsyncStorage straight in; it's the same store your adapter writes to.

Gotchas

  • Expo Go and web both work.
  • There's no sync API, so the built-in stores, zustand persist and i18n all hydrate asynchronously: gate first paint on store.useHydrated() or the splash screen, and remember the initial language is only known after initI18n() resolves.
  • Values are strings only - setItem with a non-string throws in the native module, so serialize first (the built-in stores already do).
  • Android has a 6 MB total-size default; raise it with AsyncStorage_db_size_in_MB in gradle.properties if you store more.
  • Swapping stacks: bun run setup --storage kv-store|mmkv replaces src/lib/storage.ts. Keys stay the same readynative:* strings but the data lives in a different backend, so existing values do not move - users start fresh. No migration ships.

Remove it

Every app needs a storage option, so there is no none to fall back to - you switch instead. While modules/ exists (a tree set up with --keep-modules), one call does it:

bun run setup --storage kv-store --yes --keep-modules

A finalized tree can't switch: clone a fresh copy of your tier repo, run setup there with the new option and port your code across - see Can I change a module after setup?.

Reference

Everything below is generated from modules/storage/async-storage/module.json - the same file bun run setup reads, so it is what actually lands in your repo.

Install

bun run setup --storage async-storage

Module id: storage/async-storage.

Dependencies

PackageVersionKind
@react-native-async-storage/async-storage2.2.0dependency (expo install)

Privacy

Required-reason APIs: UserDefaults (CA92.1), FileTimestamp (C617.1).

Files

3 files copied to the project root
  • __mocks__/@react-native-async-storage/async-storage.ts
  • src/lib/__tests__/storage-async-storage.test.ts
  • src/lib/storage.ts

On this page

Get ReadyNative