Saltar al contenido

Lección 13 de 20 · Lectura y práctica

Almacenamiento local con AsyncStorage y SQLite

Tipo de lección: VideoConcepto claveEl almacenamiento local es como la memoria de corto plazo de tu aplicacion movil. Mientras que las APIs externas son como consultar una biblioteca remota, el almacenamiento local es tu cuaderno.

Del concepto a la práctica

Taller de esta lección

Elige almacenamiento según la forma de consulta. Preferencias como modo: 'oscuro' caben en un valor serializado; pedidos con id, fecha, líneas y estado se benefician de registros consultables. En ambos casos define una clave o esquema y trata la lectura ausente como estado inicial, no como corrupción automática.

Ejemplo resuelto

AsyncStorage puede guardar cart:v1 con [{"id":"p1","qty":2}]. Al leer, parsea JSON y valida que cada elemento tenga id y cantidad positiva. Para tres pedidos filtrados por estado, SQLite permite preguntar por status = 'pending' sin cargar todo.

Pruébalo

  1. Define la versión de la clave.

  2. Guarda datos serializados.

  3. Lee y valida la forma.

  4. Usa una consulta acotada para registros estructurados.

Error frecuente: guardar objetos directamente donde se espera texto. Corrige usando serialización y captura de errores de parseo.

Ejercicio: persiste p1 con cantidad 2 y recupera.

Comprueba tu resultado

mismo id y cantidad; si la clave no existe, el carrito recuperado es [], no undefined.

JSON válido, hidratación y SQL actual

El valor serializado correcto es [{"id":"p1","qty":2}], con comillas dobles. Instala e importa AsyncStorage desde @react-native-async-storage/async-storage, no desde react-native. getItem('cart:v1') puede devolver null; en ese caso inicia []. Para contenido presente usa JSON.parse y verifica array, IDs strings únicos, qty entero positivo y productos conocidos. Un registro corrupto debe mostrar error/recuperación explícita, no declararse restaurado.

javascript
function leerCarrito(texto){
  if(texto===null) return [];
  const filas=JSON.parse(texto);
  if(!Array.isArray(filas)||filas.some(f=>!f||!['p1','p2','p3'].includes(f.id)||!Number.isInteger(f.qty)||f.qty<=0))
    throw new Error('Carrito inválido');
  if(new Set(filas.map(f=>f.id)).size!==filas.length) throw new Error('IDs repetidos');
  return filas;
}

Termina hidratación antes de permitir al efecto guardar un carrito vacío. Guarda con setItem(clave,JSON.stringify(filas)) y trata errores de lectura/escritura. AsyncStorage no cifra: usa un almacén apropiado para secretos. No enseñes límites fijos2/6/10MB como universales de plataforma. SQLite actual usa openDatabaseAsync, execAsync para esquema fijo, runAsync para parámetros y getAllAsync para consultas; el viejo openDatabase/transacción no es intercambiable. Fixture pedidos o1=pending,o2=paid,o3=pending; WHERE status=? con parámetro pending devuelve o1/o3 si ordenas por id. AsyncStorage, SQLite.

AsyncStorage guarda preferencias; SQLite organiza registros consultables; los secretos quedan fuera del almacenamiento común.
CursaloMapa de práctica
Elige dónde guardar cada dato

Distingue preferencias simples de datos estructurados que requieren consultas. AsyncStorage y SQLite no son un almacén adecuado para secretos en texto claro; usa las capacidades seguras de la plataforma y define sincronización y borrado.

Ver la infografía en tamaño completo ↗

Tipo de lección: Video

Concepto clave

El almacenamiento local es como la memoria de corto plazo de tu aplicacion movil. Mientras que las APIs externas son como consultar una biblioteca remota, el almacenamiento local es tu cuaderno de notas personal donde guardas informacion que necesitas acceder rapidamente, incluso sin conexion a internet.

En React Native con Expo, tenemos dos opciones principales: AsyncStorage y SQLite. AsyncStorage es como una caja simple donde guardas cosas con etiquetas - perfecta para datos pequenos como preferencias de usuario o tokens. SQLite es como un archivador organizado con carpetas y documentos - ideal para datos estructurados complejos que necesitan consultas avanzadas.

La decision entre uno y otro depende del volumen y complejidad de tus datos. Para menos de 2MB y datos simples, AsyncStorage es suficiente. Para mas datos o relaciones complejas, SQLite es tu mejor opcion.

Como funciona en la practica

Vamos a implementar un sistema de almacenamiento para una app de tareas. Primero, instalaremos las dependencias necesarias. Para AsyncStorage, ya viene incluido en React Native, pero con Expo necesitamos instalar una version especifica.

Paso 1: Instalar dependencias. Abre tu terminal y ejecuta:

npx expo install @react-native-async-storage/async-storage
expo install expo-sqlite

Paso 2: Configurar AsyncStorage para guardar el tema de la app (claro/oscuro). Paso 3: Configurar SQLite para guardar las tareas con fecha, prioridad y estado. Paso 4: Implementar sincronizacion entre almacenamiento local y servidor cuando haya conexion.

Codigo en accion

Veamos primero como usar AsyncStorage para guardar preferencias del usuario:

import AsyncStorage from '@react-native-async-storage/async-storage';

// Guardar un valor
const saveUserPreference = async (key, value) => {
  try {
    await AsyncStorage.setItem(key, JSON.stringify(value));
    console.log('Preferencia guardada correctamente');
  } catch (error) {
    console.error('Error al guardar:', error);
  }
};

// Ejemplo de uso
await saveUserPreference('@theme', 'dark');
await saveUserPreference('@notifications', true);

// Leer un valor
const getUserPreference = async (key) => {
  try {
    const value = await AsyncStorage.getItem(key);
    return value != null ? JSON.parse(value) : null;
  } catch (error) {
    console.error('Error al leer:', error);
    return null;
  }
};

// Ejemplo de lectura
const theme = await getUserPreference('@theme');
console.log('Tema actual:', theme);

Ahora, veamos SQLite para datos mas complejos. Antes teniamos solo AsyncStorage, pero al crecer la app necesitamos mas estructura:

import * as SQLite from 'expo-sqlite';

// Abrir o crear base de datos
const db = SQLite.openDatabase('tasks.db');

// Inicializar tabla
const initDatabase = () => {
  db.transaction(tx => {
    tx.executeSql(
      'CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, completed BOOLEAN, priority INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP)',
      [],
      () => console.log('Tabla creada/existe'),
      (_, error) => console.error('Error creando tabla:', error)
    );
  });
};

// Insertar una tarea
const addTask = (title, priority = 1) => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        'INSERT INTO tasks (title, completed, priority) VALUES (?, ?, ?)',
        [title, false, priority],
        (_, result) => resolve(result.insertId),
        (_, error) => reject(error)
      );
    });
  });
};

// Consultar tareas pendientes
const getPendingTasks = () => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        'SELECT * FROM tasks WHERE completed = ? ORDER BY priority DESC, created_at ASC',
        [false],
        (_, { rows }) => resolve(rows._array),
        (_, error) => reject(error)
      );
    });
  });
};

// Ejemplo de uso
await initDatabase();
const taskId = await addTask('Comprar leche', 2);
const pendingTasks = await getPendingTasks();
console.log('Tareas pendientes:', pendingTasks);

Errores comunes

1. No manejar errores en operaciones asincronas: Siempre usa try-catch con AsyncStorage y callbacks de error con SQLite. Sin esto, tu app puede crashear silenciosamente.

2. Exceder el limite de AsyncStorage: AsyncStorage tiene limite de ~6MB en iOS y ~10MB en Android. Si necesitas mas, migra a SQLite antes de que los usuarios tengan problemas.

3. No serializar datos complejos: AsyncStorage solo guarda strings. Si intentas guardar objetos directamente, se convertiran a [object Object]. Usa JSON.stringify() y JSON.parse().

4. Bloques de transaccion muy grandes en SQLite: Agrupa operaciones relacionadas en una sola transaccion, pero no metas todo en una. Divide en transacciones logicas.

5. Olvidar cerrar conexiones de base de datos: Con SQLite, aunque Expo maneja algunas cosas, en apps complejas considera cerrar conexiones cuando no las uses.

Checklist de dominio

  • Puedo instalar y configurar tanto AsyncStorage como SQLite en un proyecto Expo
  • Se cuando usar AsyncStorage (datos simples) vs SQLite (datos complejos)
  • Implemento manejo de errores robusto en todas las operaciones de almacenamiento
  • Serializo y deserializo datos correctamente para AsyncStorage
  • Creo tablas y ejecuto consultas SQL basicas en SQLite
  • Manejo transacciones apropiadamente para mantener integridad de datos
  • Implemento una estrategia de sincronizacion entre almacenamiento local y servidor remoto

Implementa un sistema de notas con almacenamiento local

Crea una app de notas que permita:

  1. Crear nuevas notas con titulo y contenido
  2. Listar todas las notas ordenadas por fecha de creacion
  3. Marcar notas como favoritas
  4. Buscar notas por texto en titulo o contenido
  5. Persistir los datos localmente

Paso 1: Configura un nuevo proyecto Expo o usa uno existente

Paso 2: Instala las dependencias necesarias para AsyncStorage y SQLite

Paso 3: Decide que sistema usar (AsyncStorage o SQLite) basado en los requisitos

Paso 4: Implementa las funciones CRUD para las notas

Paso 5: Crea una interfaz basica con React Native para probar la funcionalidad

Paso 6: Agrega la funcionalidad de busqueda

Paso 7: Implementa la marcacion de favoritos

Paso 8: Prueba que los datos persistan al cerrar y reabrir la app

Pistas
  • Considera usar SQLite por la necesidad de busqueda y ordenacion
  • Para la busqueda, usa la clausula LIKE de SQL o filtra arrays en JavaScript
  • Guarda las fechas como timestamps para facilitar el ordenamiento

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con React Native y Expo: Interfaces, Estado y APIs de Dispositivo

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.