eduardweb.
React Native & ExpoIntermediar#performance#react-native#android#flashlist

FlatList vs FlashList pe Android ieftin: Cum am crescut FPS-ul de la 22 la 58

De Cristian Barbu, 4 aug. 2026 · 7 vizualizări · 3 like-uri

Postat 4 aug. 2026
typescript
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { FlashList } from '@shopify/flash-list';

interface Product {
  id: string;
  title: string;
  price: string;
}

export const ProductList = ({ products }: { products: Product[] }) => {
  return (
    <View style={styles.container}>
      <FlashList
        data={products}
        renderItem={({ item }) => (
          <View style={styles.card}>
            <Text style={styles.title}>{item.title}</Text>
            <Text>{item.price}</Text>
          </View>
        )}
        estimatedItemSize={88}
        keyExtractor={(item) => item.id}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, width: '100%' },
  card: { height: 88, padding: 16, borderBottomWidth: 1, borderColor: '#ccc' },
  title: { fontWeight: 'bold' }
});

Dacă ai dezvoltat vreodată o aplicație în React Native și ai testat-o doar pe iPhone-ul tău de serviciu, ai o surpriză neplăcută când ajunge în producție. Săptămâna trecută am optimizat feed-ul pentru un client din retail — o listă infinită cu vreo 1.200 de produse, imagini, badge-uri și prețuri. Pe simulatorul de iOS totul rula la 60 FPS impecabil. Pe un Samsung Galaxy A12 (procesor Helio P35, 3GB RAM), aplicația agăța atât de tare încât scroll-ul devenea inutilizabil.

Am activat Perf Monitor-ul nativ din dev menu și am zis că e timpul să înlocuiesc clasicul FlatList cu FlashList de la Shopify, să văd dacă recomandările de pe forumuri sunt doar hype sau chiar fac treabă.

Unde crapă FlatList-ul pe hardware ieftin?

FlatList din React Native e practic un wrapper peste VirtualizedList. Când faci scroll rapid, el unmount-ează componentele care ies din ecran și creează altele noi pentru cele care intră. Pe procesoare slabe cu 8 nuclee ieftine, procesul ăsta continuu de alloc/dealloc pentru elementele native omoară thread-ul de UI și bridge-ul JS.

Cu FlatList, pe Samsung-ul A12 am înregistrat următoarele cifre triste:

  • JS FPS: Pica frecvent între 12 și 22 FPS.
  • UI FPS: Sacada pe la 25-30 FPS, cu freeze-uri vizibile de câte o secundă la scroll rapid.
  • RAM: A urcat constant până la 340 MB, pentru că garbage collector-ul nu făcea față la viteza cu care instanțiam și distrugeam celule.

Intrarea în scenă a FlashList

Spre deosebire de FlatList, FlashList folosește conceptul de view recycling (similar cu RecyclerView din Android nativ sau UICollectionView din iOS). În loc să distrugă componentele când ies din viewport, le păstrează instanțiate nativ și doar le înlocuiește datele când intră în ecran alte iteme.

Inlocuirea e aproape drop-in, cu adăugarea prop-ului obligatoriu estimatedItemSize.

Rezultatele din Perf Monitor pe același telefon și cu exact aceleași date:

  • JS FPS: A urcat la 55 - 58 FPS constant.
  • UI FPS: Rămâne lipit de 59 - 60 FPS, chiar și la scroll agresiv.
  • RAM: Stabilizat la 185 MB. O scădere de aproape 45% în consumul de memorie.

Răspunsul la touch a devenit instant, fără intervalele alea enervante în care ecranul rămânea alb (blank spaces) așteptând ca JavaScript-ul să randeze celulele următoare.

Unde apar problemele? (Trade-off-uri reale)

Nu e totul numai lapte și miere, altfel echipa de core din React Native ar fi înlocuit FlatList definitiv.

  1. Trebuie să nimerești dimensiunea celulei: Câmpul estimatedItemSize e critic. Dacă pui o valoare total greșită (de exemplu pui 100px și celula ta are de fapt 350px), lista va avea jump-uri vizibile de scroll și recalculări agresive de layout.
  2. Layout-uri dinamice complexe: Dacă ai celule cu înălțimi extrem de variabile (un post are text de 2 rânduri, altul are carusel foto și 500 de caractere), reuzarea celulelor poate genera glitch-uri de render scurte, în care vechiul conținut se vede o fracțiune de secundă înainte să se actualizeze.
  3. State-ul local din celule: Dacă renderItem-ul tău conține state local (useState în interiorul cardului), reuzarea instanței va păstra state-ul vechi dacă nu ești atent să resetezi totul corect prin key sau prin sincronizare pe ID-ul entității.

Concluzie

Dacă lista ta are elemente omogene sau dimensiuni ușor de anticipat, FlashList este un upgrade obligatoriu. Economisești resurse masive pe telefoanele entry-level și scapi de senzația de aplicație web împachetată prost într-un Webview.

Voi mai folosiți FlatList în producție pe proiecte mari sau ați trecut toți pe FlashList / LegendList?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.