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 ();
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:
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:
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.