Skip to main content
This guide will help you start using expo-native-storage in your Expo app. You’ll learn how to store and retrieve data using both async and sync APIs.

Basic usage

expo-native-storage provides two APIs: async (Promise-based) and sync (immediate). Choose the one that fits your use case.

Async API (Promise-based)

The async API is ideal when you need to coordinate with other async operations:
import Storage from 'expo-native-storage';

// Store a string value
await Storage.setItem('username', 'john_doe');

// Retrieve a string value
const username = await Storage.getItem('username');
console.log(username); // 'john_doe'

// Store an object
await Storage.setObject('user', { 
  name: 'John Doe', 
  email: '[email protected]',
  age: 30 
});

// Retrieve an object
const user = await Storage.getObject('user');
console.log(user?.name); // 'John Doe'

// Remove an item
await Storage.removeItem('username');

// Clear all stored data
await Storage.clear();

Sync API (Immediate)

The sync API is perfect for app initialization and settings screens where you need immediate results:
import Storage from 'expo-native-storage';

// Store a string value synchronously
Storage.setItemSync('username', 'john_doe');

// Retrieve a string value synchronously
const username = Storage.getItemSync('username');
console.log(username); // 'john_doe'

// Store an object synchronously
Storage.setObjectSync('user', { 
  name: 'John Doe', 
  email: '[email protected]',
  age: 30 
});

// Retrieve an object synchronously
const user = Storage.getObjectSync('user');
console.log(user?.name); // 'John Doe'

// Remove an item synchronously
Storage.removeItemSync('username');

// Clear all stored data synchronously
Storage.clearSync();

Real-world example: Theme persistence

Here’s a practical example showing how to persist and load a user’s theme preference:
App.tsx
import { useEffect, useState } from 'react';
import { View, Text, Switch, StyleSheet } from 'react-native';
import Storage from 'expo-native-storage';

export default function App() {
  const [isDark, setIsDark] = useState(false);
  const [isLoading, setIsLoading] = useState(true);

  // Load theme preference on app start
  useEffect(() => {
    const loadTheme = async () => {
      const savedTheme = await Storage.getItem('theme');
      if (savedTheme === 'dark') {
        setIsDark(true);
      }
      setIsLoading(false);
    };
    
    loadTheme();
  }, []);

  // Save theme preference when it changes
  const toggleTheme = async () => {
    const newTheme = !isDark;
    setIsDark(newTheme);
    await Storage.setItem('theme', newTheme ? 'dark' : 'light');
  };

  if (isLoading) {
    return <Text>Loading...</Text>;
  }

  return (
    <View style={[styles.container, isDark && styles.dark]}>
      <Text style={[styles.text, isDark && styles.darkText]}>
        Theme: {isDark ? 'Dark' : 'Light'}
      </Text>
      <Switch value={isDark} onValueChange={toggleTheme} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  dark: {
    backgroundColor: '#000',
  },
  text: {
    fontSize: 20,
    marginBottom: 20,
    color: '#000',
  },
  darkText: {
    color: '#fff',
  },
});

Using the sync API for theme loading

For immediate access during app initialization, use the sync API:
App.tsx
import { useState } from 'react';
import Storage from 'expo-native-storage';

export default function App() {
  // Load theme synchronously during component initialization
  const [isDark, setIsDark] = useState(() => {
    const savedTheme = Storage.getItemSync('theme');
    return savedTheme === 'dark';
  });

  const toggleTheme = () => {
    const newTheme = !isDark;
    setIsDark(newTheme);
    // Save synchronously for immediate persistence
    Storage.setItemSync('theme', newTheme ? 'dark' : 'light');
  };

  return (
    <View style={[styles.container, isDark && styles.dark]}>
      <Text style={[styles.text, isDark && styles.darkText]}>
        Theme: {isDark ? 'Dark' : 'Light'}
      </Text>
      <Switch value={isDark} onValueChange={toggleTheme} />
    </View>
  );
}
The sync API eliminates the loading state entirely, providing instant access to stored values during component initialization.

Working with multiple values

expo-native-storage supports batch operations for working with multiple keys:
import Storage from 'expo-native-storage';

// Set multiple items at once
await Storage.multiSet({
  'username': 'john_doe',
  'email': '[email protected]',
  'theme': 'dark'
});

// Get multiple items at once
const values = await Storage.multiGet(['username', 'email', 'theme']);
console.log(values);
// { username: 'john_doe', email: '[email protected]', theme: 'dark' }

Next steps

Async vs Sync APIs

Learn when to use async vs sync methods for optimal performance.

Best Practices

Discover patterns for error handling, type safety, and data management.

API Reference

Explore all available methods and their complete type signatures.

Performance

Learn why expo-native-storage is faster than AsyncStorage.

Build docs developers (and LLMs) love