FlatList
¿Por qué FlatList?
typescript1// ❌ Mal - ScrollView con map (renderiza todo) 2<ScrollView> 3 {items.map(item => <Item key={item.id} data={item} />)} 4</ScrollView> 5 6// ✅ Bien - FlatList (renderiza solo lo visible) 7<FlatList 8 data={items} 9 renderItem={({ item }) => <Item data={item} />} 10 keyExtractor={item => item.id.toString()} 11/>
FlatList Básico
typescript1import { FlatList, View, Text, StyleSheet } from "react-native"; 2 3interface Product { 4 id: number; 5 name: string; 6 price: number; 7} 8 9const PRODUCTS: Product[] = [ 10 { id: 1, name: "iPhone 15", price: 999 }, 11 { id: 2, name: "AirPods Pro", price: 249 }, 12 { id: 3, name: "MacBook Pro", price: 1999 }, 13]; 14 15function ProductList() { 16 const renderProduct = ({ item }: { item: Product }) => ( 17 <View style={styles.productCard}> 18 <Text style={styles.productName}>{item.name}</Text> 19 <Text style={styles.productPrice}>${item.price}</Text> 20 </View> 21 ); 22 23 return ( 24 <FlatList 25 data={PRODUCTS} 26 renderItem={renderProduct} 27 keyExtractor={(item) => item.id.toString()} 28 /> 29 ); 30} 31 32const styles = StyleSheet.create({ 33 productCard: { 34 padding: 16, 35 backgroundColor: "white", 36 marginBottom: 8, 37 marginHorizontal: 16, 38 borderRadius: 8, 39 }, 40 productName: { 41 fontSize: 18, 42 fontWeight: "600", 43 marginBottom: 4, 44 }, 45 productPrice: { 46 fontSize: 16, 47 color: "#007AFF", 48 }, 49});
Props Importantes de FlatList
typescript1<FlatList 2 data={items} 3 renderItem={renderItem} 4 keyExtractor={(item) => item.id} 5 // Separadores 6 ItemSeparatorComponent={() => ( 7 <View style={{ height: 1, backgroundColor: "#eee" }} /> 8 )} 9 // Estados vacíos 10 ListEmptyComponent={<Text style={styles.empty}>No hay items</Text>} 11 // Header y Footer 12 ListHeaderComponent={<Text style={styles.header}>Lista de Productos</Text>} 13 ListFooterComponent={<Text style={styles.footer}>Fin de la lista</Text>} 14 // Estilos 15 contentContainerStyle={styles.contentContainer} 16 // Scroll 17 showsVerticalScrollIndicator={false} 18 // Refresh 19 refreshing={refreshing} 20 onRefresh={handleRefresh} 21 // Infinite scroll 22 onEndReached={loadMore} 23 onEndReachedThreshold={0.5} 24/>
Pull to Refresh
typescript1import { useState } from "react"; 2import { FlatList, RefreshControl } from "react-native"; 3 4function ProductList() { 5 const [products, setProducts] = useState(INITIAL_PRODUCTS); 6 const [refreshing, setRefreshing] = useState(false); 7 8 const onRefresh = async () => { 9 setRefreshing(true); 10 11 // Simular fetch 12 await new Promise((resolve) => setTimeout(resolve, 2000)); 13 14 // Actualizar datos 15 setProducts([...INITIAL_PRODUCTS]); 16 setRefreshing(false); 17 }; 18 19 return ( 20 <FlatList 21 data={products} 22 renderItem={renderProduct} 23 keyExtractor={(item) => item.id.toString()} 24 refreshControl={ 25 <RefreshControl 26 refreshing={refreshing} 27 onRefresh={onRefresh} 28 tintColor="#007AFF" 29 /> 30 } 31 /> 32 ); 33}
Recursos
1 recurso disponible
Reto de Lectura
Reto de LecturaPrincipiante35 min🔴 Sin IA
Reto de Lectura — La lista que congela el teléfono
Dos listas de 2,000 contactos: una congela el teléfono 4 segundos, la otra abre al instante. Explica la diferencia con lo que pasa por dentro.
Ambas versiones muestran los mismos 2,000 contactos. La A tarda ~4 segundos en abrir y el scroll va a tirones; la B abre al instante. Explica QUÉ hace cada una por dentro y encuentra además los 2 defectos que quedan en la B.
Versión A:
jsx1<ScrollView> 2 {contactos.map((c) => ( 3 <View key={c.id} style={styles.fila}> 4 <Image source={{ uri: c.foto }} style={styles.avatar} /> 5 <Text>{c.nombre}</Text> 6 </View> 7 ))} 8</ScrollView>
Versión B:
jsx1<FlatList 2 data={contactos} 3 renderItem={({ item }) => ( 4 <View style={{ flexDirection: "row", padding: 12, borderBottomWidth: 1, borderColor: "#eee" }}> 5 <Image source={{ uri: item.foto }} style={styles.avatar} /> 6 <Text>{item.nombre}</Text> 7 </View> 8 )} 9/>
Preguntas:
- ¿Cuántos componentes monta cada versión al abrir la pantalla? ¿Qué hace FlatList con los items que no se ven?
- La consola de B muestra una advertencia amarilla. ¿Cuál es y qué consecuencia tiene ignorarla?
- Hay un segundo defecto en B relacionado con los estilos del renderItem. ¿Cuál es y por qué importa EN una lista (aunque sería tolerable fuera de una)?
- Escribe la versión B corregida.
Clase 9 de 31 en la ruta Desarrollo movil