FlashList vs FlatList
Compensaciones de FlashList de Shopify, reciclaje y lista de verificación de migración - cuando la lista predeterminada no es suficientemente rápida.
Busca en todas las páginas de la documentación
Compensaciones de FlashList de Shopify, reciclaje y lista de verificación de migración - cuando la lista predeterminada no es suficientemente rápida.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
import { FlashList } from "@shopify/flash-list";
import { StyleSheet, Text, View } from "react-native";
interface Post {
id: string;
title: string;
}
const ESTIMATED_ROW_HEIGHT = 88;
export function PostFeed({ posts }: { posts: Post[] }) {
return (
<FlashList
data={posts}
estimatedItemSize={ESTIMATED_ROW_HEIGHT}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.row}>
<Text style={styles.title} numberOfLines={2}>
{item.title}
</Text>
</View>
)}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
}
const styles = StyleSheet.create({
row: { paddingHorizontal: 16, paddingVertical: 12, backgroundColor: "#fff" },
title: { fontSize: 16, fontWeight: "600", color: "#0f172a" },
separator: { height: 8 },
});Cuándo usarlo: Feeds cargados de imágenes, cronogramas de chat o cualquier lista donde la generación de perfiles muestre caídas de fotogramas durante el desplazamiento rápido en dispositivos Android de rango medio.
import { memo, useCallback } from "react";
import { FlashList } from "@shopify/flash-list";
import { Image, StyleSheet, Text, View } from "react-native";
interface Product {
id: string;
name: string;
price: string;
imageUrl: string;
}
const PRODUCTS: Product[] = Array.from({ length: 200 }, (_, i) => ({
id: `p-${i}`,
name: `Product ${i + 1}`,
price: `$${(9.99 + (i % 50)).toFixed(2)}`,
imageUrl: `https://picsum.photos/seed/${i}/120/120`,
}));
const ESTIMATED_ROW_HEIGHT = 96;
const ProductRow = memo(function ProductRow({ item }: { item: Product }) {
return (
<View style={styles.row}>
<Image source={{ uri: item.imageUrl }} style={styles.thumb} />
<View style={styles.meta}>
<Text style={styles.name} numberOfLines={1}>
{item.name}
</Text>
<Text style={styles.price}>{item.price}</Text>
</View>
</View>
);
});
export default function ProductFeedScreen() {
const renderItem = useCallback(
({ item }: { item: Product }) => <ProductRow item={item} />,
[],
);
return (
<View style={styles.screen}>
<FlashList
data={PRODUCTS}
estimatedItemSize={ESTIMATED_ROW_HEIGHT}
keyExtractor={(item) => item.id}
renderItem={renderItem}
drawDistance={250}
contentContainerStyle={styles.list}
/>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, backgroundColor: "#f8fafc" },
list: { paddingVertical: 8 },
row: {
flexDirection: "row",
alignItems: "center",
gap: 12,
paddingHorizontal: 16,
paddingVertical: 10,
backgroundColor: "#fff",
minHeight: ESTIMATED_ROW_HEIGHT,
},
thumb: { width: 72, height: 72, borderRadius: 8, backgroundColor: "#e2e8f0" },
meta: { flex: 1 },
name: { fontSize: 16, fontWeight: "600", color: "#0f172a" },
price: { fontSize: 14, color: "#2563eb", marginTop: 4 },
});Lo que esto demuestra:
estimatedItemSize establecido en la altura típica de la fila - requerido para las matemáticas de diseño de FlashList.minHeight en la fila alinea el tamaño renderizado con la estimación para un desplazamiento estable.memo en ProductRow se empareja con el reciclaje de vistas - las filas deben tolerar la reutilización sin estado obsoleto.drawDistance={250} pre-renderiza ligeramente por delante de la ventana de visualización para reducir destellos en blanco durante el desplazamiento rápido.keyExtractor / renderItem que FlatList - la migración es principalmente adiciones de props.estimatedItemSize porque diseña contenido antes de que cada fila se mida - la estimación controla los cálculos de desplazamiento hasta que llega la medida real.data, renderItem, keyExtractor, separadores, encabezados, onEndReached.| Aspecto | FlatList | FlashList |
|---|---|---|
| Reciclaje | Montar/desmontar filas | Revincula un grupo fijo de vistas |
| Sugerencia de tamaño | getItemLayout opcional | estimatedItemSize requerido |
| Altura variable | Funciona; remide según sea necesario | Funciona; ajusta la estimación + overrideItemLayout |
| Paquete | Integrado en RN | Dependencia @shopify/flash-list |
| Superficie de API | Superconjunto (maduro) | Casi drop-in; algunas diferencias de props |
| Mejor ajuste | Listas cortas/medias, configuración | Feeds largos, imágenes, chat, cuadrículas de mercado |
npx expo install @shopify/flash-listFlatList - FlashList de @shopify/flash-listestimatedItemSize: Mide una fila típica en DevTools o especificaciones de diseño (incluye padding).item.minHeight o altura fija cercana a la estimación cuando sea posible.overrideItemLayout por tipo de elemento o mantén listas separadas por variante de diseño.onEndReached: El comportamiento del umbral es similar pero verifica guardias de paginación.FlashList con encabezados adhesivos o mantén SectionList hasta que necesites la ganancia de rendimiento.console.time alrededor de sesiones de desplazamiento.// Antes
import { FlatList } from "react-native";
<FlatList data={items} renderItem={...} keyExtractor={...} />
// Después
import { FlashList } from "@shopify/flash-list";
<FlashList
data={items}
estimatedItemSize={72}
renderItem={...}
keyExtractor={...}
/>| Prop | Propósito |
|---|---|
estimatedItemSize | Altura promedio de la fila en dp - requerido |
drawDistance | Píxeles más allá de la ventana de visualización para pre-renderizar (predeterminado ~250) |
overrideItemLayout | Anulación de tamaño por índice para filas heterogéneas |
estimatedListSize | { height, width } cuando se conoce el tamaño de la lista temprano |
getItemType | Devuelve una cadena de tipo para que los grupos de reciclaje separen diseños |
<FlashList
data={items}
estimatedItemSize={120}
getItemType={(item) => (item.pinned ? "pinned" : "normal")}
overrideItemLayout={(layout, item) => {
layout.size = item.pinned ? 160 : 96;
}}
renderItem={renderItem}
/>useState dentro de una fila puede mostrar el estado del elemento anterior durante un fotograma.useEffect sin dependencias propias se activan en el elemento incorrecto.item o mapas padre (expandedIds); las filas deben ser funciones puras de props.import type { FlashListProps, ListRenderItem } from "@shopify/flash-list";
interface Article {
id: string;
headline: string;
}
type ArticleListProps = Pick<
FlashListProps<Article>,
"data" | "onEndReached" | "refreshing" | "onRefresh"
> & {
onPress: (article: Article) => void;
};
function ArticleList({ data, onPress, ...rest }: ArticleListProps) {
const renderItem: ListRenderItem<Article> = useCallback(
({ item }) => <ArticleRow article={item} onPress={() => onPress(item)} />,
[onPress],
);
return (
<FlashList
data={data}
estimatedItemSize={104}
keyExtractor={(item) => item.id}
renderItem={renderItem}
{...rest}
/>
);
}@shopify/flash-list, no de react-native.FlashListProps<T> refleja FlatListProps<T> para la mayoría de props de lista.| Parámetro | Tipo | Descripción |
|---|---|---|
estimatedItemSize | number | Altura promedio del elemento en píxeles independientes de densidad - requerido |
data | readonly T[] | Array de origen (igual que FlatList) |
renderItem | ListRenderItem<T> | Renderizador de filas - debe ser estable para reciclaje |
drawDistance | number | Distancia de pre-renderizado más allá de los bordes de la ventana de visualización |
overrideItemLayout | (layout, item, index) => void | Establece layout.size para alturas de elemento conocidas |
getItemType | (item, index) => string | Separa grupos de reciclaje por variante de diseño |
Falta estimatedItemSize - FlashList advierte y vuelve a adivinanzas de diseño deficientes; el desplazamiento se siente roto. Solución: Siempre establécelo; mide filas reales en el simulador.
Estimación lejos de la realidad - Una estimación de 200px en filas de 80px causa salto cuando la medida se corrige. Solución: Mide la altura de fila p50; usa overrideItemLayout para valores atípicos.
Componentes de fila con estado - useState para "me gusta" dentro de la fila muestra el estado de "me gusta" del elemento anterior después del reciclaje. Solución: Almacena estado de interacción en mapas padre/item o extraData.
Migración sin memo - El reciclaje amplifica re-renderizados innecesarios dentro de filas. Solución: memo componentes de fila; renderItem estable con useCallback.
Usar FlashList para 10 filas de configuración - Dependencia adicional y ajuste sin ganancia medible. Solución: Mantén FlatList o ScrollView hasta que la generación de perfiles demuestre la necesidad.
Ignorar dimensiones de imagen - Las imágenes que se cargan de forma asincrónica cambian la altura de fila después del primer diseño, causando salto en ambos tipos de lista; peor cuando la estimación es incorrecta. Solución: width/height fijos en Image, fondo de marcador de posición o proporción de aspecto conocida.
Asumir paridad de API del 100% - Algunos props de borde difieren; prueba ListHeaderComponent, numColumns y desplazamiento anidado. Solución: Lee la documentación de @shopify/flash-list para tu versión; ejecuta la lista de verificación de migración en el dispositivo.
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
FlatList | Listas predeterminadas, configuración, < 100 filas, sin quejas de rendimiento | La generación de perfiles muestra tartamudeos durante el desplazamiento en dispositivos de destino |
FlashList | Feeds largos, imágenes, chat, mercado | Listas triviales donde el tamaño del paquete importa más |
SectionList | Datos agrupados con encabezados de sección adhesivos | Feed plano de tipo único - FlashList es más simple |
Legend List / otras listas comunitarias | Evaluación de alternativas a FlashList | Quieres compatibilidad con Expo mantenida por Shopify primero |
ScrollView + map | Contenido estático muy corto | Cualquier lista que se desplace durante segundos a 60 fps |
Casi - intercambia la importación, agrega estimatedItemSize, y audita componentes de fila para seguridad de reciclaje. La mayoría de props (data, renderItem, keyExtractor, onEndReached, refresh) funcionan igual. Prueba tus diseños específicos de encabezado/pie de página y multi-columna.
FlashList posiciona filas antes de que todas se midan. La estimación controla la matemática del desplazamiento hasta que se conoce la altura real de cada fila. Sin él, la lista no puede virtualizarse eficientemente.
Mide una fila renderizada típica en el inspector de diseño, incluido el padding y los separadores. Usa la altura mediana si las filas varían ligeramente. Para tipos mixtos, usa getItemType + overrideItemLayout.
En lugar de destruir una vista de fila cuando se desplaza fuera de pantalla, FlashList la revincula a los datos de un nuevo elemento. El mismo árbol de vista nativa se reutiliza - como la reutilización de celdas de UITableView en iOS. Los componentes de fila no deben mantener estado local obsoleto.
Sí - npx expo install @shopify/flash-list fija una versión compatible para tu SDK. No se requiere código nativo personalizado en flujos de trabajo estándar de Expo.
FlashList admite encabezados adhesivos y diseños heterogéneos, pero SectionList sigue siendo la opción ergonómica para agrupación { title, data }. Migra el renderizado de elementos a patrones de FlashList cuando el feed plano es el cuello de botella.
Distancia en píxeles más allá de la ventana de visualización visible donde FlashList pre-renderiza elementos. Los valores más altos reducen destellos en blanco durante el desplazamiento rápido a costa de más trabajo por fotograma. El valor predeterminado suele ser suficiente; aumenta en feeds cargados de imágenes si ves parpadeo.
FlashList usa estimatedItemSize y overrideItemLayout en su lugar. overrideItemLayout te permite establecer layout.size por índice cuando se conocen las alturas sin medir.
Sí - se admiten diseños de cuadrícula. Establece numColumns y asegúrate de que estimatedItemSize refleja la altura de fila (no el ancho de celda). Prueba el espaciado horizontal y los grupos de reciclaje para celdas de cuadrícula.
estimatedItemSize a la altura real.minHeight en filas.overrideItemLayout para variantes altas/cortas conocidas.Sí - especialmente con reciclaje. Combina memo en la fila, renderItem estable y estado solo de props. Ver List Performance Tuning.
FlashList admite el mismo patrón - pasa estado externo que afecta el renderizado de filas para que las vistas recicladas se actualicen cuando cambia la selección o el tema.
Para listas muy cortas, FlatList evita el ajuste de estimación y el paquete adicional. Mide - no migres prematuramente.
Ver @shopify/flash-list en Bibliotecas esenciales para instalar, plugins de configuración y props avanzados.
El mismo patrón onEndReached / onEndReachedThreshold que FlatList. Guarda capturas con una ref de carga. Ver Infinite Scroll & Pagination.
memo, manejadores estables y conceptos de windowSize que se aplican a ambas listasVersiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0 y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 16 jul 2026