Chapter 8 of 12
~18 min read
Local Storage, Secure Storage & SQLite
AsyncStorage vs localStorage, expo-secure-store for credentials, expo-sqlite for relational data.
1. Why `localStorage` is Dangerous on Mobile
In Cordova, many developers used standard browser localStorage.setItem(). In mobile OSes, the underlying WebView cache can be arbitrarily purged by the OS when memory is low! Furthermore, synchronous localStorage locks the UI thread during heavy reads.
Cordova localStorage
// Fragile & synchronous
localStorage.setItem('user_session', JSON.stringify(session));
const data = JSON.parse(localStorage.getItem('user_session'));
React Native AsyncStorage & SecureStore
// 1. General Preferences
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('theme', 'dark');
const theme = await AsyncStorage.getItem('theme');
// 2. Secure Storage (Tokens, Passwords)
import * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('auth_token', 'jwt_xyz');
const token = await SecureStore.getItemAsync('auth_token');
2. Modern SQLite in React Native
Replacing cordova-sqlite-storage with modern expo-sqlite using async queries:
expo-sqlite Implementation
import * as SQLite from 'expo-sqlite';
async function setupDatabase() {
const db = await SQLite.openDatabaseAsync('myapp.db');
// Create table
await db.execAsync(`
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT);
`);
// Insert with prepared statement
await db.runAsync('INSERT INTO notes (text) VALUES (?)', 'Migrating to React Native');
// Query rows
const allRows = await db.getAllAsync('SELECT * FROM notes');
console.log('Notes:', allRows);
}