Curso de Fundamentos de React Native

Instalación de Async Storage para persistencia de datos en React Native

Curso de Fundamentos de React Native

Contenido del curso

Módulo 3: Interactividad y Manejo de Datos

Instalación de Async Storage para persistencia de datos en React Native

Platzi DayPlatzi Day

Todos los cursos GRATIS

Se acaba en:
:::

Resumen

Para que tus hábitos no se pierdan al cerrar la app, aquí verás cómo integrar persistencia con Async Storage, ordenar tus types, crear utils de fecha en date.ts y montar una arquitectura con context y reducer para hidratar, agregar y hacer toggle de hábitos con control de racha. Todo claro, modular y listo para escalar.

¿Cómo instalar y preparar Async Storage?

Antes de guardar datos localmente, instala la librería Async Storage. Asegúrate de crear una Storage Key clara y una versión para futuras migraciones.

  • Instala la librería según el recurso compartido.
  • Define una llave de almacenamiento: STORAGE_KEY = "Hábitos".
  • Define una versión: STORAGE_VERSION = 1.
  • Usa la llave para leer, escribir y actualizar datos.
  • Mantén el state inicial con: habits vacíos y loading: true.

Código orientativo:

// storage.ts export const STORAGE_KEY = 'Hábitos'; export const STORAGE_VERSION = 1;

¿Qué utilidades de fecha necesitas en date.ts?

Centraliza la lógica de fechas en un util date.ts para reutilizar y tipar mejor tus operaciones: primer día, mismo día, día de ayer y formato ISO.

  • Primer día: normaliza la fecha al inicio del día.
  • Mismo día: compara dos fechas sin horas.
  • Día de ayer: calcula la referencia del día anterior.
  • ISO: guarda y compara en formato estándar de JavaScript.

Código orientativo:

// utils/date.ts export const startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate()); export const isSameDate = (a: Date, b: Date) => startOfDay(a).getTime() === startOfDay(b).getTime(); export const yesterday = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate() - 1); export const toISO = (d: Date) => startOfDay(d).toISOString();

¿Cómo organizar types y el modelo de hábito?

Separa tus modelos y tipos en una carpeta llamada types. Así el código en TSX/JSX queda limpio y escalable.

  • Crea la carpeta: types.
  • Define la prioridad con tres valores conocidos del proyecto.
  • Define el hábito con campos mínimos y fechas para la racha.
  • Incluye identificador único para cada hábito.

Código orientativo:

// types/habits.ts export type Priority = string; // tres tipos ya definidos en el proyecto. export interface Habit { id: string; title: string; priority: Priority; streak: number; // racha. createdAtISO: string; // fecha de creación en ISO. lastDoneISO?: string; // última vez completado en ISO. }

¿Cómo diseñar context y reducer para hábitos?

Crea una carpeta para tus contexts. Ahí vivirá la “central de mando” con state, acciones y reducer para hidratar, agregar y hacer toggle. Controla loading, mapea hábitos y actualiza la racha con fechas.

  • Estado inicial: loading: true, habits: [].
  • Acciones con payload tipado: hydrate, add, toggle.
  • Usa un switch por action.type.
  • En hydrate: loading = false y hábitos desde el payload.
  • En add: crea id único con la fecha y guarda en ISO.
  • En toggle: valida si ya se hizo hoy, calcula racha con “ayer”, y actualiza fechas.
// context/habits.tsx import { Habit, Priority } from '../types/habits'; import { toISO, isSameDate, yesterday } from '../utils/date'; type HabitsState = { loading: boolean; habits: Habit[] }; type HydrateAction = { type: 'hydrate'; payload: Habit[] }; type AddAction = { type: 'add'; payload: { title: string; priority: Priority } }; type ToggleAction = { type: 'toggle'; payload: { id: string; todayISO: string } }; type HabitsAction = HydrateAction | AddAction | ToggleAction; export const initialState: HabitsState = { loading: true, habits: [] }; export function habitsReducer(state: HabitsState, action: HabitsAction): HabitsState { switch (action.type) { case 'hydrate': { return { loading: false, habits: action.payload }; } case 'add': { const { title, priority } = action.payload; const now = new Date(); const newHabit: Habit = { id: now.getTime().toString(), title, priority, streak: 0, createdAtISO: toISO(now), lastDoneISO: undefined, }; return { ...state, habits: [newHabit, ...state.habits] }; } case 'toggle': { const { id, todayISO } = action.payload; const today = new Date(todayISO); const yest = yesterday(today); const updated = state.habits.map(h => { if (h.id !== id) return h; const doneToday = h.lastDoneISO && isSameDate(new Date(h.lastDoneISO), today); if (doneToday) { const newStreak = Math.max(0, (h.streak ?? 0) - 1); return { ...h, streak: newStreak, lastDoneISO: undefined }; } let newStreak = 1; if (h.lastDoneISO && isSameDate(new Date(h.lastDoneISO), yest)) { newStreak = (h.streak ?? 0) + 1; } return { ...h, streak: newStreak, lastDoneISO: toISO(today) }; }); return { ...state, habits: updated }; } default: return state; } }

¿Qué acciones maneja el reducer y su payload?

  • hydrate: recibe hábitos y desactiva loading.
  • add: usa title y priority del payload.
  • toggle: requiere id y el día de hoy para validar fechas.

¿Cómo actualiza el toggle la racha y las fechas?

  • Si ya está hecho hoy: deselecciona y resta 1 a la racha.
  • Si se completó ayer: suma 1 a la racha.
  • Si no, inicia la racha en 1.
  • Actualiza lastDoneISO con la fecha actual en ISO.

¿Te gustaría ver el provider para conectar esta lógica con la UI y Async Storage? Cuéntame en los comentarios qué parte quieres profundizar primero.