Library / SDK
sunnylqm/react-native-storage avatar
sunnylqm/react-native-storage

react-native-storage: a key-id local cache with sync hooks for React Native and the browser

local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

3,035 stars264 forksJavaScriptMIT

At a glance

What is it?
react-native-storage wraps AsyncStorage on React Native and localStorage on the web behind one promise-based API with size limits, expiry and a sync callback. It is a small cache layer, not a database, and the README itself now points elsewhere.
Who is it for?
Adopt react-native-storage when you want one small promise-based cache layer over AsyncStorage and localStorage, with expiry and a sync hook, and you accept that the README now recommends useQuery with createAsyncStoragePersister for newer work. Skip it when you need relational queries, transactions or a storage engine that survives a key-id eviction you did not plan for.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 76 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem react-native-storage solves for React Native and web apps

AsyncStorage on React Native and localStorage in the browser are both simple key-value stores, and neither gives you expiry, a capacity ceiling, or a way to refill a missing record from a server. react-native-storage sits on top of both and adds those three things behind one API. The package description calls it a local storage wrapper for react native (AsyncStorage) and browser (localStorage), and the README repeats that framing. The intended audience is an app developer who wants cached user records, login state or page data to expire on its own and to be refetched transparently when it is gone. Two data shapes are supported. A key-only record, such as loginState, is stored permanently unless you remove it. A key-id record, such as user with id 1001, participates in the size limit and can be evicted. That split is the design centre of the library, and it is also the source of most confusion, because the bulk operations only touch one of the two shapes.

How the key-id map, expiry and sync callback fit together

The constructor takes size, storageBackend, defaultExpires, enableCache and sync. size defaults to 1000 key-ids, and the README states that by default the 1001st key-id record will overwrite the first one. If you later load that first record, you get a NotFoundError or a sync call, which is the documented eviction behaviour rather than a bug. Expiry is per record: expires on save overrides defaultExpires, and null means never expire. Loading has two flags that change the data flow. autoSync defaults to true, so a missing or expired record triggers the sync method whose name matches the data key. syncInBackground defaults to true, so expired data is returned immediately while the sync runs. Setting syncInBackground to false makes the load wait for fresh data, which the README describes as slower. The sync method receives one object containing id and syncParams, and it can return a value or a promise. The README example fetches a user, calls storage.save with the same key and id, and returns the parsed user; on failure it throws. If storageBackend is not set, the README warns that data will be lost after reload, because the in-memory cache is then the only store.

Installing react-native-storage and saving a first record

The README gives two package manager lines. The wrapper itself is react-native-storage, and on React Native you also need the AsyncStorage package, which the README names as @react-native-async-storage/async-storage.

bash
npm install react-native-storage
npm install @react-native-async-storage/async-storage

You then create one storage instance and export it. The README notes that key names must not contain underscores, and that storageBackend should be AsyncStorage on React Native or window.localStorage on the web.

js
import Storage from 'react-native-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';

const storage = new Storage({
  size: 1000,
  storageBackend: AsyncStorage,
  defaultExpires: 1000 * 3600 * 24,
  enableCache: true,
  sync: {}
});

export default storage;

A first real use is saving a login state under a key-only record and reading it back. Because no expires value is passed, defaultExpires applies. The promise resolves with the stored object, and any failure, including a missing record, lands in catch with an error whose name is NotFoundError or ExpiredError.

js
storage.save({
  key: 'loginState',
  data: { userid: 'some userid', token: 'some token' },
  expires: 1000 * 3600
});

storage.load({ key: 'loginState' })
  .then(ret => console.log(ret.userid))
  .catch(err => console.warn(err.name));

Where the key-only and key-id split bites you

The README marks several behaviours with exclamation points, and they are worth reading as limitations rather than footnotes. getIdsForKey and getAllDataForKey return only key-id records under a key; key-only data is not included. clearMapForKey clears key-id records under a key and leaves key-only data intact. clearMap removes all key-id data and, per the README, key-only data is not cleared. So a logout routine built on clearMap will wipe cached user records and leave loginState behind. The size cap applies to key-id records only, so key-only data can accumulate without ever counting against size. There is no query language, no index and no transaction; getAllDataForKey is the closest thing to a scan, and it loads every record under one key into memory. The library is also backend-agnostic by design, which means the durability and quota rules of the underlying store still apply. On the web that is localStorage, with its synchronous API and per-origin quota. The README does not document rollback, migration between storage shapes, or what happens when the backend write itself fails, so those paths are yours to handle.

The README now recommends TanStack Query instead

The most direct alternative comes from the project's own README. It recommends useQuery together with createAsyncStoragePersister, describing that combination as cleaner, more elegant and more powerful, and pointing at the TanStack Query v5 React quick-start page. The difference in approach is real. react-native-storage is a cache with a callback: you call load, and if the record is missing or expired the library calls your sync function. TanStack Query is a request and cache manager: queries own their fetch functions, staleness and refetch policy, and createAsyncStoragePersister writes that query cache to AsyncStorage so it survives a reload. If your data is server state with refetch and invalidation rules, the query model fits better and you stop hand-writing sync methods. If you want a thin wrapper that stores arbitrary blobs with an expiry timestamp and no fetch semantics, react-native-storage is the smaller dependency. A second comparison point sits in the related searches: MMKV appears as a storage option people search for alongside this library. MMKV is a different kind of tool, an embedded key-value store rather than a promise wrapper over AsyncStorage, and the repository does not describe an integration between the two.

Maintenance, licence and the cost of upgrading

The repository is not archived, and the last push was on 2026-07-19. The package.json lists version 1.0.1, with no recent releases retrieved, so the published version and the repository state may not move together. The build runs through rollup: yarn build cleans lib/, runs rollup -c and copies src/storage.d.ts into lib/. Published entry points are lib/storage.cjs.js for main, lib/storage.esm.js for module and jsnext:main, src/storage.js for the react-native field, and lib/storage.d.ts for typings. Tests run with jest, with bail set to true and a setup file at jestSupport/mockStorage.js, so the suite stops at the first failing test. The licence is MIT, which permits commercial use and modification provided the copyright notice and permission notice are kept; this is a description of the licence text, not legal advice. Two runtime dependencies are listed, opencollective-postinstall and opencollective, and the package declares a postinstall script that runs opencollective-postinstall. That means installing the package triggers a funding message, which is worth knowing if your install pipeline runs with scripts disabled or logs install output. Upgrading is cheap for a project that stays on the documented API, because the surface is save, load, remove, getIdsForKey, getAllDataForKey, clearMapForKey and clearMap. The risk sits in the sync contract: the sync method name must equal the data key, so renaming a key means renaming a sync function in the same change.

Editorial conclusion

Adopt react-native-storage when you want one small promise-based cache layer over AsyncStorage and localStorage, with expiry and a sync hook, and you accept that the README now recommends useQuery with createAsyncStoragePersister for newer work. Skip it when you need relational queries, transactions or a storage engine that survives a key-id eviction you did not plan for. Before committing, verify three things in the repository: that the sync function name matches the data key exactly, that your key and id strings contain no underscores, and that your size value is large enough for the number of key-id records you expect to write.

Frequently asked questions

What is AsyncStorage in React Native, and how does react-native-storage relate to it?

AsyncStorage is the key-value store the README names as the React Native backend, installed as @react-native-async-storage/async-storage. react-native-storage is a wrapper over it that adds expiry, a key-id size cap and sync callbacks. The README notes that if storageBackend is not set, data will be lost after reload.

How do I install react-native-storage?

The README gives npm install react-native-storage and npm install @react-native-async-storage/async-storage, or the equivalent yarn add lines. The AsyncStorage package is the React Native backend you pass as storageBackend.

Why does react-native-storage call a sync method when I load data?

autoSync defaults to true, so a record that is missing or expired triggers the sync method whose name matches the data key. The sync method receives id and syncParams, and it can return a value or a promise. Setting autoSync to false stops that call.

Does react-native-storage work in the browser as well as in React Native?

Yes. The README describes it as a wrapper for both React Native apps using AsyncStorage and web apps using localStorage, and says to pass window.localStorage as storageBackend for the web. The same save, load and sync API applies to both.

What happens when the react-native-storage size limit is reached?

The size parameter defaults to 1000 key-ids, and the README states that by default the 1001st key-id record overwrites the first one. A later load of that first record produces a NotFoundError or invokes sync. Key-only records do not count against this limit.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. sunnylqm/react-native-storage on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sunnylqm-react-native-storage.svg)](https://hysenlabs.com/projects/sunnylqm-react-native-storage)