Implementación del tab Explore con FlatList y carga asíncrona
Clase 19 de 23 • Curso de Fundamentos de React Native
Contenido del curso
- 5

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

Componentes reutilizables en React Native
14:50 - 7

StyleSheet y Flexbox en React Native
11:24 - 8

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

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

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

Pressable vs TouchableOpacity en React Native
09:37
- 12

Crear un carrusel con ScrollView horizontal
10:51 - 13

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

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

Context y Provider para estado global de hábitos
12:08 - 16

AsyncStorage context para persistir hábitos
13:19 - 17

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

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

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

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

Cámara y galería en React Native
16:01
Optimiza la experiencia del tab explore en una app de hábitos: carrusel horizontal con FlatList, estados por categoría, carga asíncrona con useEffect, manejo de errores con try/catch y alertas nativas. Aquí verás cómo pasar de ScrollView a un carrusel eficiente, reutilizar secciones y conectar el servicio de Explore con el de hábitos sin duplicar código.
¿Cómo implementar el tab explore con flatlist horizontal?
Al migrar a FlatList obtienes rendimiento y un carrusel horizontal limpio. La lista recibe la data de sugerencias, un renderItem que entrega la tarjeta y un keyExtractor basado en el id. Además, se prepara un estado de carga con estilos de sombras para mostrar un placeholder mientras llegan los datos del servicio.
// renderItem: retorna la tarjeta reutilizable
const renderItem = ({ item }) => (
<ExploreCard
emoji={item.emoji}
title={item.title}
subtitle={item.subtitle}
onPress={() => Alert.alert(item.title, 'Acción ejecutada.')}
/>
);
// keyExtractor: id único por sugerencia
const keyExtractor = (item) => String(item.id);
// carrusel horizontal con FlatList
<FlatList
horizontal
data={data}
keyExtractor={keyExtractor}
renderItem={renderItem}
showsHorizontalScrollIndicator={false}
/>
¿Cómo crear el renderitem y el keyextractor?
- Usa un identificador estable para el keyExtractor.
- Retorna la tarjeta con emoji, título, subtítulo y acción.
- Evita lógica extra dentro de renderItem: delega en la tarjeta.
- Muestra alerta nativa con Alert.alert al seleccionar.
¿Cómo construir la sección reutilizable por categoría?
Agrupa título y carrusel en una sección que reciba props. Así reduces duplicación y renders innecesarios.
// sección reutilizable por categoría
const Section = ({ title, data /* Suggestion[] | null */ }) => (
<View style={{ marginVertical: 12 }}>
<Text style={styles.sectionTitle}>{title}</Text>
{data ? (
<FlatList horizontal data={data} renderItem={renderItem} keyExtractor={keyExtractor} />
) : (
// placeholder de carga con sombras
<ExploreCard loading />
)}
</View>
);
¿Qué estados y tipos definen las sugerencias dinámicas?
Se manejan dos categorías como estados independientes: energía y focus. Ambos usan el tipo suggestion definido en el servicio. Así, cada carrusel recibe su propio arreglo o null cuando aún no hay data. La tarjeta deja de “quemar” la prioridad, ya que ahora se lee desde la sugerencia.
// estados por categoría y flag de carga
const [energy, setEnergy] = useState(/* Suggestion[] | null */ null);
const [focus, setFocus] = useState(/* Suggestion[] | null */ null);
const [isLoading, setIsLoading] = useState(false);
// mapeo a la tarjeta: usa s.title y prioridad de la data
<ExploreCard
title={s.title}
priority={s.priority}
/* ...otros props */
/>
¿Cómo mapear suggestion a la tarjeta y prioridad?
- Usa s.title como título que llega del servicio.
- Toma priority desde la sugerencia, no hardcodees valores.
- Mantén el tipo suggestion consistente en todo el flujo.
- Gestiona energía y focus como fuentes separadas de data.
¿Cómo cargar datos con useeffect y manejar errores?
Al entrar al tab, un useEffect dispara una función async que llama al servicio de sugerencias para ambas categorías. Se controla el estado de carga, se actualizan los estados locales y se captura cualquier error con console.warn. Al finalizar, se restablece el flag para indicar que terminó la operación.
useEffect(() => {
let mounted = true;
const loadSuggestions = async () => {
setIsLoading(true);
try {
const a = await suggestFirst('energia');
const b = await suggestFirst('focus');
if (!mounted) return;
setEnergy(a);
setFocus(b);
} catch (e) {
console.warn('No se pudieron cargar las sugerencias', e);
} finally {
setIsLoading(false);
}
};
loadSuggestions();
return () => { mounted = false; };
}, []);
¿Cómo manejar errores y alertas sin fricción?
- Implementa try/catch para capturar fallos de red o servicio.
- Usa console.warn para diagnóstico no intrusivo.
- Muestra Alert.alert al añadir desde el carrusel: comunica éxito al usuario.
- Asegura un placeholder visible mientras se resuelve la promesa.
¿Te gustaría ver más patrones para listas horizontales y estados compartidos entre tabs? Cuéntame qué categoría agregarías o qué mejora probarías a continuación.