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

React Native: Când au sens useMemo, React.memo și FlashList (și când faci over-engineering)

De Andreea Crăciun, 14 aug. 2026 · 5 vizualizări · 2 like-uri

Postat acum 2 zile
typescript
import React, { memo } from 'react';
import { Text, StyleSheet, Pressable } from 'react-native';
import { FlashList } from '@shopify/flashlist';

type ProductItemProps = {
  title: string;
  price: number;
  onPress: (id: string) => void;
  id: string;
};

// memoizăm item-ul pentru că FlashList îi va refolosi instanța
const ProductItem = memo(({ id, title, price, onPress }: ProductItemProps) => (
  <Pressable style={styles.card} onPress={() => onPress(id)}>
    <Text style={styles.title}>{title}</Text>
    <Text style={styles.price}>{price} RON</Text>
  </Pressable>
));

export const ProductList = ({ items, onSelect }: { items: any[]; onSelect: (id: string) => void }) => {
  return (
    <FlashList
      data={items}
      renderItem={({ item }) => (
        <ProductItem id={item.id} title={item.title} price={item.price} onPress={onSelect} />
      )}
      estimatedItemSize={72}
      keyExtractor={(item) => item.id}
    />
  );
};

const styles = StyleSheet.create({
  card: { height: 72, padding: 12, borderBottomWidth: 1, borderColor: '#eee' },
  title: { fontSize: 16, fontWeight: '600' },
  price: { color: '#666', marginTop: 4 }
});

La un proiect de e-commerce cu peste 12.000 de produse în catalog, feed-ul principal agăța groaznic pe telefoane Android mai slabe. Primul reflex al echipei a fost să arunce useCallback, useMemo și React.memo pe fiecare componentă și funcție din codebase, sperând că se rezolvă magic. Rezultatul? Nicio îmbunătățire la FPS, dar am adăugat un overhead stupid de memorie și cod greu de urmărit.

După vreo doi ani de profilat ecrane cu React DevTools și Flipper, am învățat pe pielea mea ce mișcă acul cu adevărat în performanța de React Native.

useMemo și useCallback nu sunt gratuite

Fiecare useCallback sau useMemo înseamnă alocare de memorie pentru array-ul de dependențe și o verificare în plus la fiecare render. Dacă calculezi o chestie banală – gen filtrezi 20 de elemente dintr-un array sau pasezi un handler pe un buton nativ – costul memoizării este mai mare decât recalcularea directă.

Când merită cu adevărat:

  • useMemo: Doar pentru transformări grele de date (operații complexe pe sute sau mii de obiecte) sau când generezi o referință nouă de obiect/array care intră ca prop într-un copil deja învelit în React.memo.
  • useCallback: Exclusiv când trimiți acea funcție ca prop către o componentă copil optimizată cu React.memo sau o folosești ca dependență în useEffect. În rest, recrearea unei funcții inline e extrem de ieftină pentru engine-ul JavaScript (Hermes).
  • React.memo: Are sens doar pe noduri din arbore care se rerandează des deși props-urile lor rămân identice (de exemplu, rândurile dintr-o listă lungă). Dacă trimiți props dinamice la fiecare render al părintelui, React.memo face comparația degeaba și doar consumă CPU.

FlatList vs FlashList (Shopify)

FlatList din core-ul React Native funcționează prin distrugerea și recrearea completă a componentelor pe măsură ce faci scroll (windowSize, maxToRenderPerBatch). Pe liste mari, asta generează garbage collection masiv și frame drops vizibile.

Shopify a scos FlashList cu un concept preluat din native (RecyclerView / UICollectionView): reciclarea celulelor. În loc să distrugă componentele când ies din ecran, FlashList le păstrează instanțiate și doar le actualizează props-urile cu noile date.

La migrarea feed-ului nostru de la FlatList la FlashList am văzut:

  • FPS constant: de la 38-42 FPS pe un Samsung A-series la 58-60 FPS stabili la scroll rapid.
  • Timp de render inițial redus cu aproape 40% pe ecrane dense.

Trade-off-ul? Trebuie să configurezi corect estimatedItemSize. Dacă pui o valoare complet greșită, lista va avea layout jumps deranjante. De asemenea, fiindcă componentele sunt reciclate, trebuie să ai grijă la starea locală din celule (de preferat deloc – ține totul în datele din listă).

Regula mea după zeci de ecrane optimizate

Nu optimiza dinainte. Pornește Flipper sau React Profiler, identifică componentele care ard cicluri CPU inutil și abia atunci izolează-le. Pune FlashList din start dacă lista ta depășește 50 de elemente sau conține layout-uri complexe.

Voi ce experiențe ați avut cu FlashList pe producție? Ați prins cazuri unde a făcut figuri la layout-uri dinamice?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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