FlatList y Performance
FlatList es el componente de lista virtualizada de React Native. La virtualización significa que solo renderiza los elementos actualmente visibles en pantalla más un pequeño buffer. Si tienes 10.000 items, FlatList renderiza solo los ~20 visibles en pantalla, no los 10.000. Cuando el usuario hace scroll, destruye los elementos que salen de la pantalla y crea los nuevos que entran. Esto hace que listas enormes funcionen fluidamente con poca memoria.
FlatList requiere tres props principales: data (el array de datos), renderItem (función que recibe un item y devuelve el componente a renderizar), y keyExtractor (función que devuelve un ID único para cada item, necesario para la virtualización). Para separadores entre items usa ItemSeparatorComponent. Para la cabecera usa ListHeaderComponent. Para secciones agrupadas (como contactos por letra) usa SectionList. Si tienes pocas decenas de items, ScrollView con un map() es más simple.
import { FlatList, View, Text, RefreshControl } from "react-native";
import { useState, useCallback } from "react";
const DATOS = Array.from({ length: 1000 }, (_, i) => ({
id: String(i),
nombre: `Usuario ${i}`,
puntos: Math.floor(Math.random() * 1000),
}));
function Tarjeta({ item, onPress }) {
return (
<TouchableOpacity onPress={() => onPress(item)} style={styles.tarjeta}>
<Text style={styles.nombre}>{item.nombre}</Text>
<Text style={styles.puntos}>{item.puntos} XP</Text>
</TouchableOpacity>
);
}
export default function ListaUsuarios() {
const [refrescando, setRefrescando] = useState(false);
// useCallback evita recrear la función en cada render
const renderItem = useCallback(({ item }) => (
<Tarjeta item={item} onPress={(u) => console.log(u)} />
), []);
const keyExtractor = useCallback((item) => item.id, []);
const onRefresh = useCallback(async () => {
setRefrescando(true);
await new Promise(r => setTimeout(r, 1500)); // Simula fetch
setRefrescando(false);
}, []);
return (
<FlatList
data={DATOS}
keyExtractor={keyExtractor}
renderItem={renderItem}
// Optimizaciones
getItemLayout={(_, index) => ({
length: 60, offset: 60 * index, index
})}
initialNumToRender={15}
maxToRenderPerBatch={10}
windowSize={5}
// Pull to refresh
refreshControl={
<RefreshControl
refreshing={refrescando}
onRefresh={onRefresh}
tintColor="#00E5A0"
/>
}
// Separador
ItemSeparatorComponent={() => <View style={{ height: 1, backgroundColor: "#333" }} />}
/>
);
}
Practica esta lección
Resuelve los ejercicios del curso de React Native en la app, gratis y con corrección automática.
Empezar a practicar