Context y Provider para estado global de hábitos
Clase 15 de 22 • Curso de Fundamentos de React Native
Contenido del curso
Módulo 2: Construcción de la Interfaz de Usuario
- 5

Uso de constantes y condicionales en archivos TSX de React Native
10:36 min - 6

Componentes reutilizables en React Native
14:50 min - 7

StyleSheet y Flexbox en React Native
11:24 min - 8

Paleta de colores con hooks en React Native
13:07 min - 9

useState para interfaces dinámicas en React Native
12:12 min - 10

Estado interactivo en React Native con useCallback
13:24 min - 11

Pressable vs TouchableOpacity en React Native
09:37 min
Módulo 3: Interactividad y Manejo de Datos
- 12

Crear un carrusel con ScrollView horizontal
10:51 min - 13

Diferencias entre ScrollView y FlatList para listas grandes
09:47 min - 14

Instalación de Async Storage para persistencia de datos en React Native
14:54 min - 15

Context y Provider para estado global de hábitos
Viendo ahora - 16

Context y provider para persistir hábitos en React Native
13:19 min - 17

React Native: Provider de animación con confetti
11:58 min - 18

Cómo crear una ExploreCard específica para iOS y Android
09:48 min - 19

Implementación del tab Explore con FlatList y carga asíncrona
12:49 min - 20

Contexto de perfil con persistencia y avatar aleatorio usando IA
12:32 min - 21

Cámara y galería en React Native
16:01 min
Módulo 4: Visualización de Listas y Contenido
Crear un estado global de hábitos confiable en React es más sencillo si organizas bien el context, el provider y las actualizaciones con useReducer y useEffect. Aquí verás cómo hidratar el estado desde AsyncStorage, cómo persistir cambios sin errores y cómo preparar las acciones de agregar y seleccionar hábitos. Todo, paso a paso, con buenas prácticas y mensajes de control en consola.
¿Cómo definir el context y el provider en React?
Para centralizar la lógica, se define un tipo que agrupe hábitos, estado de carga y funcionalidades. Luego, se crea el context con ese tipo y un valor por defecto nulo si no está disponible. El provider expone el estado y las funciones, devolviendo un ReactNode.
- Define un tipo con hábitos, loading y funciones de negocio.
- Crea el context con createContext y usa el tipo o null como valor inicial.
- Implementa el provider que retornará el Provider del contexto.
- Integra useReducer con un reducer y un initialState.
// Esquema orientativo import React, { createContext, useReducer, useEffect } from 'react'; type HabitsContextType = { habits: any[]; loading: boolean; addHabit: (...args: any[]) => void; selectHabit: (...args: any[]) => void; }; const HabitsContext = createContext<HabitsContextType | null>(null); function HabitsProvider({ children }: { children: React.ReactNode }) { const [state, dispatch] = useReducer(reducer, initialState); // acciones se implementan más abajo en el flujo const addHabit = (...args: any[]) => dispatch({ type: 'add', payload: args }); const selectHabit = (...args: any[]) => dispatch({ type: 'select', payload: args }); return ( <HabitsContext.Provider value={{ habits: state.habits, loading: state.loading, addHabit, selectHabit }}> {children} </HabitsContext.Provider> ); }
Clave: el useReducer retorna el estado y una función de actualización (dispatch), que permite ejecutar acciones con su payload.
¿Cómo hidratar el estado con AsyncStorage y useEffect?
La hidratación carga los hábitos guardados en la “memoria de la aplicación” con AsyncStorage. Se usa useEffect asíncrono, con try/catch, para leer por la clave definida (por ejemplo, storageKey), parsear el JSON y despachar la acción de hidratar.
- Usa un useEffect inicial para leer del almacenamiento.
- Llama a getItem con la key definida: storageKey.
- Convierte el “raw” a objeto con JSON.parse.
- Despacha { type: 'hydrate', payload } con los datos.
- Maneja errores con console.warn: "No se pudo cargar hábitos".
useEffect(() => { (async () => { try { const raw = await AsyncStorage.getItem(storageKey); if (!raw) return; // sin datos, no se hidrata const data = JSON.parse(raw); dispatch({ type: 'hydrate', payload: data }); } catch (e) { console.warn('No se pudo cargar hábitos'); // opcional: asegurar un estado válido si algo falla dispatch({ type: 'hydrate', payload: [] }); } })(); }, []);
Importante: si no existe el tipo o la data, se devuelve null o un estado vacío, evitando rupturas en la UI.
¿Cómo guardar cambios y sincronizar hábitos sin errores?
Cada vez que cambian los hábitos, se debe persistir el estado. Para evitar escrituras redundantes, se usa un temporizador de guardado (save timer) y se limpia con clearTimeout antes de programar un nuevo guardado. Además, si el estado está loading, se evita guardar.
- Omite el guardado si state.loading es true.
- Usa un temporizador para controlar escrituras.
- Limpia con clearTimeout antes de programar otra operación.
- Guarda con AsyncStorage.setItem y JSON.stringify del estado.
- Controla errores: console.warn("No se pudo guardar").
- Devuelve una limpieza que cancele el temporizador activo.
const saveTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null); useEffect(() => { if (state.loading) return; // no guardar mientras hidrata if (saveTimer.current) clearTimeout(saveTimer.current); saveTimer.current = setTimeout(async () => { try { await AsyncStorage.setItem(storageKey, JSON.stringify(state.habits)); } catch (e) { console.warn('No se pudo guardar'); } }); return () => { if (saveTimer.current) clearTimeout(saveTimer.current); }; }, [state.habits, state.loading]);
¿Qué acciones del reducer se exponen en el provider?
Al final, el provider expone las funciones conectadas al dispatch para operar sobre el estado global.
- Acción "hydrate": repuebla el estado con los hábitos cargados.
- Acción "add": agrega un hábito al listado.
- Acción "select": marca o selecciona un hábito.
Resultado: el context actúa como “centro de mando”, entregando estado y funcionalidades listas para usar en la aplicación.
¿Te gustaría ver cómo implementar y consumir este provider en tus componentes? Comparte tus dudas o casos y seguimos construyendo juntos.