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);
}