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

FlatList vs FlashList: Cum am trecut de la 14 FPS la 58 FPS pe un Android ieftin

De Ana Ionescu, 3 iul. 2026 · 12 vizualizări · 3 like-uri

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

interface Post {
  id: string;
  title: string;
}

const FeedList = ({ posts }: { posts: Post[] }) => {
  return (
    <FlashList
      data={posts}
      renderItem={({ item }) => (
        <View style={{ height: 220, padding: 16 }}>
          <Text>{item.title}</Text>
        </View>
      )}
      estimatedItemSize={220} // Extrem de important pentru Android low-end
      keyExtractor={(item) => item.id}
    />
  );
};

Dacă ai lucrat la o aplicație de mobil destul de mare, știi deja că listele lungi sunt moartea pasiunii pe Android-urile ieftine. Am avut de optimizat un feed infinit cu imagini și text pe un Motorola de 600 de lei cu 2GB RAM și m-am izbit direct de limitările clasicului FlatList. Trecerea la FlashList de la Shopify a salvat proiectul de la un feedback dezastruos din partea utilizatorilor.

Problema cu FlatList pe hardware slab

FlatList vine direct din React Native și, deși e stabil, folosește o strategie destul de ineficientă pentru resurse puține: randează elementele pe măsură ce faci scroll și le distruge pe cele care ies din ecran (dacă configurezi corect windowSize). Pe un telefon lent, procesul ăsta de montare și demontare constantă a componentelor React pune la pământ procesorul.

La testele mele, pe un feed simplu cu 1500 de carduri, Perf Monitor din React Native arăta cifre de groază. UI thread-ul rămânea undeva pe la 45-50 FPS, dar JS thread-ul scădea brutal până la 12-14 FPS în timpul unui scroll rapid. Rezultatul? Utilizatorul vedea ecrane albe (blank areas) secunde bune până când se randa restul listei.

Cum rezolvă FlashList problema (și cifrele reale)

FlashList de la Shopify schimbă complet jocul prin reciclarea celulelor. În loc să distrugă componentele care ies din ecran, le păstrează structura nativă în memorie (ca un RecyclerView din Android nativ) și doar le actualizează datele.

După ce am înlocuit FlatList-ul, diferența pe același Motorola a fost vizibilă instant:

  • JS Thread: A urcat de la 14 FPS la 57-59 FPS stabil, chiar și la scroll agresiv.
  • UI Thread: S-a blocat la 60 FPS.
  • Blank areas: Au dispărut aproape complet, pentru că randarea nu mai așteaptă după garbage collector.

Marea capcană: estimatedItemSize

Nu poți doar să schimbi tag-ul și să speri că totul va merge perfect. FlashList are absolută nevoie de proprietatea estimatedItemSize. Dacă pui o valoare greșită, scroll-ul va deveni sacadat și vei avea parte de layout shifts (lista sare brusc când randează un element diferit).

În cazul meu, am măsurat înălțimea medie a unui card (care era în jur de 220px) și am pasat-o ca valoare. Dacă ai elemente cu înălțimi extrem de dinamice, FlashList va depune un efort dublu să recalculeze totul din mers.

Trade-off-ul sincer pe care trebuie să-l accepți

FlashList este excelent pentru 90% din cazuri, dar are o mare problemă cu state-ul intern al componentelor reciclate. Dacă ai un buton de "Like" în interiorul unui item din listă și ții starea locală cu un useState, când acel item iese din ecran și celula este reciclată pentru un alt element din listă, starea de "Liked" s-ar putea să rămână activă pe noul element randat.

Trebuie să te asiguri că resetezi starea manual prin key sau, mai bine, să ții tot state-ul în afara celulei (la nivel de listă sau store global).

Trecerea merită efortul doar dacă ai liste lungi și complexe de redat pe telefoane din gama low-end. Pe un iPhone 13 nu vei observa nicio diferență vizuală, însă pe Android-ul ieftin al clienților tăi va fi diferența de la cer la pământ.

Voi ați făcut trecerea la FlashList în producție sau ați rămas la FlatList optimizat la sânge?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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