mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmMobileupdated 08 Aug 2026

@react-native-async-storage/async-storage

Async Storage is unencrypted, persistent string key-value storage for React Native and supported sibling platforms. Version 3 creates named storage instances backed by SQLite on Android, iOS, and macOS, IndexedDB on the web, and a legacy single-database fallback on Windows and visionOS. It supports promise-based single and atomic batch operations. It is useful for preferences, cached responses, and state persistence, but it is not a secrets vault, relational database, or synchronous replacement for in-memory state.

Verdict

A sensible default for non-secret React Native persistence, especially when named stores and atomic batches help. Version 3 has meaningful platform floors and migration breaks, so read the migration guide before upgrading and keep credentials elsewhere.

API stability3/5Version 3 intentionally breaks the version 2 singleton contract: new code creates named instances, callbacks are gone, batch methods were renamed, merge operations disappeared, and useAsyncStorage was removed. A legacy default export remains to ease migration, and the new promise-based instance surface is compact, but this major requires edits across most existing callers rather than only a package update.
Docs5/5The official site documents current platform floors, database-name mapping on every backend, single and atomic batch operations, typed error categories, version 3 migration diffs, Expo and brownfield integration, and a Jest mock with ESM transform configuration. The README is intentionally short, but it points into a focused documentation set that answers the setup and upgrade questions likely to cause real failures.
Maintenance5/5Version 3.1.1 was published in May 2026, the GitHub repository was pushed on August 8, 2026, and the repository response showed 25 combined open issues and pull requests. It actively supports six platform targets, ships TypeScript declarations, documents a current migration, and maintains native SQLite plus web IndexedDB implementations. That is strong evidence of active ownership rather than a compatibility-only package.
Ecosystem5/5The package is the community successor to React Native's removed core AsyncStorage and receives more than six million weekly npm downloads. Its documentation includes adapters for Redux Persist, TanStack Query, Zustand, Expo, Jest, and brownfield apps, while the package exports its own types and test implementation. The main ecosystem limitation is intentional: secure secrets and queryable structured data require separate storage products.

Use it if

  • You need durable app preferences, cached JSON, onboarding flags, or persisted state across React Native restarts
  • You want separate named databases for users, caches, or features on Android, iOS, macOS, and the web
  • You need atomic setMany, getMany, and removeMany operations over groups of string keys
  • You target the current platform floors: React Native 0.76+, Android API 24+, and iOS 13+
Skip it if

Setup reality

Version 3 is not a drop-in upgrade from the long-lived singleton API. Install the package, then run pod install inside ios or macos for native projects; Expo users need a development build when native code is involved. The new default is createAsyncStorage('database-name'), and the name maps to a SQLite file directory on Android, iOS, and macOS or directly to an IndexedDB database on web. Do not include a file extension in the name. Windows and visionOS use a legacy fallback and cannot create multiple stores. The package requires React Native 0.76 on Android and iOS, 0.78 on macOS, 0.79 on Windows and visionOS, Android API 24, iOS 13, and macOS 12. Values remain strings, so JSON.stringify and JSON.parse are still application code, including schema migration and corrupt-data handling. Version 3 removes callbacks, mergeItem, multiMerge, and the useAsyncStorage hook. Its batch names are setMany, getMany, and removeMany, and the docs say writes are atomic. The default export remains as a compatibility pointer to the version 2 storage, but new integrations should not build on it. Jest cannot load the native module directly: transform the package's ESM source and use the shipped /jest in-memory mock, clearing all mock databases between tests. Production reads and writes can reject with typed native, web, SQLite, other-storage, or unknown errors, so wrap persistence boundaries. Finally, none of these platform stores encrypts data. Put credentials in Keychain, Keystore, or Expo SecureStore and reserve Async Storage for data whose disclosure does not become an account compromise.

Patterns

Create a named version 3 storagecreate-storage

import { createAsyncStorage } from '@react-native-async-storage/async-storage';

export const userStorage = createAsyncStorage('user');

Do not add .db or .sqlite to the name; the native backends normalize it into their own database path.

Store and retrieve a stringstore-string

await userStorage.setItem('theme', 'dark');

const theme = await userStorage.getItem('theme');
if (theme === null) {
  console.log('no saved theme');
}

getItem returns null for a missing key; an empty string is a real stored value and should not be treated as missing.

Serialize an object explicitlystore-json

const preferences = { theme: 'dark', fontScale: 1.1 };
await userStorage.setItem('preferences', JSON.stringify(preferences));

const raw = await userStorage.getItem('preferences');
const restored = raw === null ? null : JSON.parse(raw);

The storage only accepts strings; validate or migrate restored JSON before trusting its shape after an app update.

Remove one saved valueremove-item

await userStorage.removeItem('draft');

Removing a missing key is harmless; use a separate secure store when the value is an authentication secret.

Write several values atomicallywrite-batch

await userStorage.setMany([
  ['theme', 'dark'],
  ['locale', 'en-GB'],
  ['onboardingComplete', 'true'],
]);

Version 3 calls this setMany, not the legacy multiSet, and the documentation says the batch is atomic.

Read several keys in one operationread-batch

const values = await userStorage.getMany(['theme', 'locale']);
const byKey = new Map(values);
console.log(byKey.get('theme'));

A requested key that does not exist is returned with null, so keep missing-value handling explicit.

Delete several keys atomicallyremove-batch

await userStorage.removeMany(['draft', 'pendingUpload', 'lastError']);

The version 3 name is removeMany; old multiRemove calls belong only to the compatibility singleton.

Inspect keys before clearing one databaselist-and-clear

const keys = await userStorage.getAllKeys();
console.log('removing', keys.length, 'keys');
await userStorage.clear();

clear affects the selected named storage, but it is still destructive; do not use it for a shared compatibility store during logout unless every key is user-owned.

Handle typed storage failureshandle-storage-errors

import { SqliteStorageError } from '@react-native-async-storage/async-storage';

try {
  await userStorage.setItem('theme', 'dark');
} catch (error) {
  if (error instanceof SqliteStorageError) {
    reportStorageFailure(error.message);
  } else {
    throw error;
  }
}

The docs distinguish native-module, web, SQLite, other-storage, and unknown errors; avoid swallowing all persistence failures as cache misses.

Use the package's Jest implementationmock-in-jest

jest.mock('@react-native-async-storage/async-storage', () =>
  require('@react-native-async-storage/async-storage/jest')
);

const { clearAllMockStorages } = require('@react-native-async-storage/async-storage/jest');
afterEach(() => clearAllMockStorages());

The package ships ESM source, so Jest may also need it added to transformIgnorePatterns before this mock can load.

Alternatives

PackageRegistryPick it when
react-native-mmkvnpmYou need a faster synchronous mobile key-value store and accept its native integration and different web story
expo-secure-storenpmYou are in Expo and need encrypted platform storage for small credentials or tokens
react-native-keychainnpmYou need Keychain and Keystore-backed secrets plus biometric or access-control options