Episode ini membahas penyimpanan lokal: AsyncStorage untuk data key-value, SQLite dan MMKV untuk data besar, enkripsi data sensitif, serta pola offline-first dengan queue dan strategi sinkronisasi.

Aplikasi mobile tidak selalu punya koneksi. Pengguna naik kereta, masuk lift, atau berjalan di area tanpa sinyal — dan aplikasi tetap harus bisa dipakai. Di sinilah local persistence berperan: menyimpan data di perangkat sehingga fitur tetap berjalan offline.
Episode 9 membahas pilihan penyimpanan lokal di React Native: AsyncStorage untuk data key-value, SQLite dan MMKV untuk data besar, enkripsi untuk data sensitif, lalu pola offline-first dengan queue dan strategi sinkronisasi. Episode 13 akan memperdalam sisi keamanan penyimpanan kredensial.
AsyncStorage adalah penyimpanan key-value asinkron sederhana, cocok untuk preferensi, draft, dan cache kecil. Install dari komunitas:
npm install @react-native-async-storage/async-storageimport AsyncStorage from "@react-native-async-storage/async-storage";
const KUNCI = "preferensi_user";
async function simpanPreferensi(nilai) {
await AsyncStorage.setItem(KUNCI, JSON.stringify(nilai));
}
async function bacaPreferensi() {
const mentah = await AsyncStorage.getItem(KUNCI);
return mentah ? JSON.parse(mentah) : null;
}Perhatikan AsyncStorage.setItem(KUNCI, JSON.stringify(nilai)): AsyncStorage hanya menyimpan string, jadi object harus diserialisasi dengan JSON. Jangan pernah menyimpan token atau password di sini — itu urusan episode 13.
AsyncStorage cocok untuk data kecil sampai sedang: preferensi user, tema, data form yang belum terkirim, atau cache daftar. Batasannya: semua data di-load ke memory sekaligus saat dibaca, jadi tidak ideal untuk koleksi besar atau pencarian.
Untuk data terstruktur dengan pencarian dan relasi — riwayat chat, daftar offline ribuan item — SQLite lebih tepat. Gunakan expo-sqlite untuk project Expo atau library native untuk CLI:
npx expo install expo-sqliteimport { openDatabaseSync } from "expo-sqlite";
const db = openDatabaseSync("app.db");
db.execSync(
"CREATE TABLE IF NOT EXISTS catatan (id INTEGER PRIMARY KEY, judul TEXT)"
);
db.runSync(
"INSERT INTO catatan (judul) VALUES (?)",
"Catatan pertama offline"
);MMKV (dari WeChat) menyimpan data langsung di file tanpa serialisasi JSON, dengan enkripsi opsional — jauh lebih cepat dari AsyncStorage. Cocok saat performa baca-tulis menjadi prioritas:
npm install react-native-mmkvimport { MMKV } from "react-native-mmkv";
export const storage = new MMKV({
id: "app-storage",
encryptionKey: "kunci-dari-server",
});storage.set("user", data) dan storage.getString("user") menangani penyimpanan langsung. Perhatikan encryptionKey — jangan simpan kuncinya di dalam bundle, ambil dari secure storage saat runtime.
Aturan utamanya: data publik boleh di AsyncStorage/MMKV biasa, data sensitif wajib di secure storage. Untuk field yang perlu dienkripsi tapi tetap ingin performa MMKV, pakai instance MMKV dengan encryptionKey seperti contoh di atas.
Kunci enkripsi sebaiknya diturunkan dari identitas user atau diambil dari server lewat kanal aman, bukan di-hardcode. Pola umum: user login, dapat token, lalu token tersebut menjadi bahan derivasi kunci enkripsi lokal. Episode 13 membahas tempat yang benar untuk menyimpan kunci ini.
Pendekatan offline-first: aksi user ditulis ke penyimpanan lokal sebagai antrian, lalu dikirim ke server saat koneksi pulih. Jika pengiriman gagal, aksi tetap di antrian untuk dicoba lagi:
import AsyncStorage from "@react-native-async-storage/async-storage";
async function enqueueAksi(aksi) {
const mentah = await AsyncStorage.getItem("queue_aksi");
const antrian = mentah ? JSON.parse(mentah) : [];
antrian.push({ ...aksi, waktu: Date.now() });
await AsyncStorage.setItem("queue_aksi", JSON.stringify(antrian));
}Date.now() di atas memberi timestamp agar antrian bisa diurutkan saat diproses. Aksi menunggu di queue sampai koneksi pulih, lalu dikirim satu per satu.
Saat koneksi pulih, proses antrian dalam urutan waktu, hapus aksi yang berhasil, dan tangani konflik. Tambahkan pendengar koneksi dengan @react-native-community/netinfo agar sinkronisasi otomatis saat status isConnected berubah.
Data server yang disimpan offline diberi metadata versi dan timestamp. Saat aplikasi online, bandingkan dengan server dan perbarui. Cache yang terlalu tua sebaiknya dihapus untuk menghemat storage — episode 16 akan membahas retensi data lebih lanjut.
Warning
Offline-first bukan berarti menyimpan semua data tanpa batas. Tetapkan kebijakan: berapa lama cache berlaku, aksi mana yang boleh diqueue, dan apa yang terjadi saat konflik versi. Tanpa kebijakan, storage penuh dan sinkronisasi kacau.
Episode 9 membuat aplikasi tetap berguna tanpa koneksi: AsyncStorage untuk key-value, SQLite untuk query kompleks, MMKV untuk kecepatan, enkripsi untuk data sensitif, dan pola offline-first dengan queue serta sinkronisasi otomatis.
Inti yang harus dibawa pulang:
Di episode 10 selanjutnya kita akan membahas native modules dan TurboModules: perbedaan bridge lama dengan New Architecture, interop layer, menulis module native pertama di Kotlin dan Swift, serta memanggilnya dari JavaScript.