π± Mastering Data Storage in React Native: AsyncStorage and Beyond

I'm Ogunuyo Ogheneruemu Brown, a senior software developer. I specialize in DApp apps, fintech solutions, nursing web apps, fitness platforms, and e-commerce systems. Throughout my career, I've delivered successful projects, showcasing strong technical skills and problem-solving abilities. I create secure and user-friendly fintech innovations. Outside work, I enjoy coding, swimming, and playing football. I'm an avid reader and fitness enthusiast. Music inspires me. I'm committed to continuous growth and creating impactful software solutions. Let's connect and collaborate to make a lasting impact in software development.
In mobile app development, managing data locally is essential. Whether you're storing a login token, caching user preferences, or saving offline data, React Native offers multiple tools for local persistence.
Today, weβll explore the foundational tool β AsyncStorage β and go beyond it into more powerful storage solutions like SQLite, Realm, WatermelonDB, and the FileSystem API. You'll also learn about Reactβs useEffect([]) and how screen behavior affects data fetching.
π What is AsyncStorage?
AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage system built into React Native (via the @react-native-async-storage/async-storage library).
It's ideal for:
User tokens
Simple preferences
Small, fast-access data
β Installing AsyncStorage
npx expo install @react-native-async-storage/async-storage
π§ͺ Building a Simple App with AsyncStorage
Hereβs a practical example: a UI where a driver enters their username and company, saves it locally, fetches the saved data, and can clear it.
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, StyleSheet } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
export default function App() {
const [username, setUsername] = useState('');
const [company, setCompany] = useState('');
const [savedData, setSavedData] = useState(null);
const saveData = async () => {
const userObject = { username, company };
await AsyncStorage.setItem('driverInfo', JSON.stringify(userObject));
setSavedData(userObject);
setUsername('');
setCompany('');
};
const getData = async () => {
const jsonValue = await AsyncStorage.getItem('driverInfo');
if (jsonValue) setSavedData(JSON.parse(jsonValue));
};
const clearStorage = async () => {
await AsyncStorage.removeItem('driverInfo');
setSavedData(null);
};
useEffect(() => {
getData(); // Fetch on screen mount
}, []);
return (
<View style={styles.container}>
<Text style={styles.title}>Jet Driver Setup</Text>
<TextInput style={styles.input} value={username} onChangeText={setUsername} placeholder="Username" />
<TextInput style={styles.input} value={company} onChangeText={setCompany} placeholder="Company" />
<Button title="Save" onPress={saveData} />
<View style={styles.section}>
<Text>Saved Info:</Text>
<Text>{savedData ? `${savedData.username} from ${savedData.company}` : 'No data'}</Text>
</View>
<Button title="Clear Storage" color="red" onPress={clearStorage} />
</View>
);
}
π Understanding useEffect([])
In React, the useEffect hook runs side effects like fetching data or updating storage.
useEffect(() => {
getData();
}, []);
The [] is a dependency array:
It tells React to run the effect only once, when the component is first mounted.
If the screen is unmounted (e.g., when the user logs out or navigates away), the effect will re-run when the screen is visited again.
π¦ How Long Does AsyncStorage Data Last?
It persists until you delete it.
Data survives app reloads and reboots.
Only cleared when:
You manually call
removeItem()orclear().The app is uninstalled.
π§± Storage Limits
Safe zone: ~5β6MB
Larger data may degrade performance or fail (especially on Android)
π When AsyncStorage Isn't Enough
When your app needs to store structured, larger, or relational data, consider these alternatives:
1. ποΈ SQLite
Relational database (tables, rows)
Excellent for structured data like trip records, addresses, etc.
Available via
expo-sqlite
2. π Realm DB
Object-based NoSQL database
Ideal for complex relationships and offline-first logic
Requires bare workflow (not supported in Expo Go)
3. π WatermelonDB
Built for large-scale, real-time data syncing
Highly optimized for performance
Requires advanced setup, also bare workflow only
4. π FileSystem API
Great for saving:
Logs
Reports
Raw JSON or media files
Use
expo-file-systemto write, read, and upload files
Example: Save and Upload File
import * as FileSystem from 'expo-file-system';
const saveToFile = async () => {
const path = FileSystem.documentDirectory + 'driver.json';
const data = JSON.stringify({ name: 'Carol', car: 'Toyota' });
await FileSystem.writeAsStringAsync(path, data);
return path;
};
const uploadFile = async (fileUri) => {
const formData = new FormData();
formData.append('file', {
uri: fileUri,
name: 'driver.json',
type: 'application/json',
});
await fetch('https://yourdomain.com/upload.php', {
method: 'POST',
body: formData,
headers: { 'Content-Type': 'multipart/form-data' },
});
};
π Where Is FileSystem Data Stored?
On the user's physical device
Inside a sandboxed directory only your app can access
Can be read, modified, or uploaded
It does not survive uninstallation
π§ Summary
| Tool | Best For | Expo Friendly |
| AsyncStorage | Tokens, flags, small config | β Yes |
| SQLite | Tables, relational user data | β Yes |
| Realm DB | Complex offline models | β Bare only |
| WatermelonDB | High-performance syncing | β Bare only |
| FileSystem API | Logs, reports, backup to server | β Yes |
βοΈ Final Thoughts
Local data storage is the backbone of many features β from login to logs, trip history to offline mode. AsyncStorage gives you a simple start, but understanding when to move to structured databases or files will take your app to the next level.
Keep in mind:
Use
AsyncStoragefor small, frequent-access data.Move to
SQLiteorRealmfor structured or offline data.Use
FileSystemwhen storing actual files or backups.
π Next Steps?
Add encryption for sensitive driver data.
Use
useFocusEffect()to re-run logic when a user returns to a screen.Automatically upload trip logs nightly using
FileSystem+fetch.



