Skip to content

Thereallo1026/expo-native-storage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

expo-native-storage

npm version npm downloads

Lightning-fast native storage for Expo using UserDefaults and SharedPreferences.

Why?

  • Fast: Direct native storage, no bridge delays
  • Tiny: 19x smaller bundle size compared to AsyncStorage
  • Scales: Gets faster with more operations (up to 32x on Android)
  • Web support: Falls back to localStorage
  • Native: Uses UserDefaults (iOS) & SharedPreferences (Android)

Installation

# bun
bunx expo install expo-native-storage
# npm
npx expo install expo-native-storage

Important

After installation, you must rebuild your app to link the native module. This module requires native code and will not work with Expo Go. You need a development build or production build.

# For development builds
npx expo prebuild --clean
npx expo run:ios
# or
npx expo run:android

This module requires native code and will not work with Expo Go. You need a development build or production build.

Usage

Async API (Promise-based)

import Storage from 'expo-native-storage';

// Store strings
await Storage.setItem('username', 'john_doe');
const username = await Storage.getItem('username'); // 'john_doe'

// Store objects
await Storage.setObject('user', { 
  name: 'John', 
  age: 30,
  premium: true 
});
const user = await Storage.getObject('user');

// Remove items
await Storage.removeItem('username');

// Clear all
await Storage.clear();

Sync API (Immediate, no Promises)

import Storage from 'expo-native-storage';

// Store strings synchronously
Storage.setItemSync('username', 'john_doe');
const username = Storage.getItemSync('username'); // 'john_doe'

// Store objects synchronously
Storage.setObjectSync('user', { 
  name: 'John', 
  age: 30,
  premium: true 
});
const user = Storage.getObjectSync('user');

// Remove items synchronously
Storage.removeItemSync('username');

// Clear all synchronously
Storage.clearSync();

When to use sync vs async:

  • Sync methods: App initialization, reading config on startup, settings screens
  • Async methods: When you need to coordinate with other async operations, or prefer Promise-based code

Example: Theme Storage

// Save theme preference
await Storage.setItem('theme', 'dark');

// Load on app start
const theme = await Storage.getItem('theme') || 'light';

API

Async Methods

Method Description Return
setItem(key, value) Store a string value Promise<void>
getItem(key) Get a string value Promise<string | null>
setObject(key, object) Store an object as JSON Promise<void>
getObject<T>(key) Get an object from JSON Promise<T | null>
removeItem(key) Remove an item Promise<void>
clear() Remove all items Promise<void>
multiGet(keys) Get multiple items at once Promise<Record<string, string | null>>
multiSet(items) Set multiple items at once Promise<void>

Sync Methods

Method Description Return
setItemSync(key, value) Store a string value void
getItemSync(key) Get a string value string | null
setObjectSync(key, object) Store an object as JSON void
getObjectSync<T>(key) Get an object from JSON T | null
removeItemSync(key) Remove an item void
clearSync() Remove all items void

Performance Results

Async Methods - Real Device Testing:

Platform Operations expo-native-storage AsyncStorage Improvement
Android Phone 100 ops 11ms 165ms 15x faster
200 ops ~25ms ~290ms 11x faster
500 ops ~50ms ~650ms 13x faster
1000 ops ~95ms ~1216ms 13x faster
Android Emulator 100 ops 12ms 219ms 18x faster
iOS Phone 100 ops 72ms 72ms Same speed
Bundle Size - 19.6KB 381KB 19x smaller

Sync Methods - Real Device Testing:

Platform Operations Sync Methods Async Methods Improvement
Android Phone 1000 ops 98ms 472ms 4.8x faster
iOS Phone 1000 ops 1098ms 1499ms 1.4x faster

Note on iOS Performance: iOS sync methods are limited by UserDefaults disk I/O (~1ms per write). For bulk operations (1000+ writes), consider using specialized libraries like react-native-mmkv. Sync methods are perfect for typical use cases like app settings and user preferences.

Tested on iPhone 17 Pro and Nothing Phone 3a with Android 15.
Emulator results from MacBook Pro M4 with 16GB RAM.

Performance at Scale

The performance advantage of expo-native-storage increases with usage:

Why? SharedPreferences uses in-memory caching after first access, while AsyncStorage hits the SQLite database for every operation. The more operations you perform, the bigger the performance gap becomes.

Perfect for:

  • Settings screens with many preferences
  • Offline data caching with frequent reads
  • State persistence with frequent updates
  • User session data with multiple keys

Migration from AsyncStorage

// Before (AsyncStorage)
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('key', 'value');

// After (expo-native-storage)
import Storage from 'expo-native-storage';
await Storage.setItem('key', 'value');

Drop-in replacement with zero breaking changes.

Platform Notes

  • iOS: Uses UserDefaults (synchronous, limited to ~1MB per key)
  • Android: Uses SharedPreferences (synchronous, good for small data)
  • Web: Uses localStorage (synchronous, ~5-10MB limit)

Requirements

  • Expo SDK 50+
  • Development builds (not available in Expo Go)

Troubleshooting

Error: Cannot find native module 'ExpoNativeStorage'

This error means the native module isn't linked. To fix:

  1. Rebuild your app after installing:

    bunx expo prebuild --clean
    bunx expo run:ios  # or run:android
  2. Clear caches if the issue persists:

    # clear Metro bundler cache
    bunx expo start -c
    
    # clear all caches
    rm -rf node_modules
    bun install  # or npm install
    bunx expo prebuild --clean
  3. Verify installation:

    • Check that expo-native-storage is in your package.json
    • Make sure you're using a development build, not Expo Go
    • For iOS: Check that ExpoNativeStorage appears in your Podfile.lock
    • For Android: Check that the module is in your build.gradle dependencies

Still having issues?

Open an issue on GitHub with:

  • Your Expo SDK version
  • React Native version
  • Platform (iOS/Android)
  • Full error message
  • Whether you're using Expo Go or a development build

License

MIT

About

Drop-in replacement for AsyncStorage, 8KB packed, native.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published