eduardweb.
React Native & ExpoIntermediar#performance#react-native#javascript

React Native Performance: Când chiar ajută memo, useCallback și FlashList

De George Iliescu, 1 iul. 2026 · 11 vizualizări · 3 like-uri

Postat 1 iul. 2026
typescript
import React, { useCallback } from 'react';
import { Text, TouchableOpacity, StyleSheet } from 'react-native';
import { FlashList } from '@shopify/flash-list';

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

// Învelim componenta în React.memo pentru a evita rerandările inutile
const ProductCard = React.memo(({ item, onPress }: { item: Product; onPress: (id: string) => void }) => {
  return (
    <TouchableOpacity style={styles.card} onPress={() => onPress(item.id)}>
      <Text>{item.title}</Text>
    </TouchableOpacity>
  );
});

export function ProductList({ items }: { items: Product[] }) {
  // useCallback păstrează referința funcției stabilă între randări
  const handlePress = useCallback((id: string) => {
    console.log('Product pressed:', id);
  }, []);

  const renderItem = useCallback(({ item }: { item: Product }) => (
    <ProductCard item={item} onPress={handlePress} />
  ), [handlePress]);

  return (
    <FlashList
      data={items}
      renderItem={renderItem}
      estimatedItemSize={80}
      keyExtractor={(item) => item.id}
    />
  );
}

const styles = StyleSheet.create({
  card: { height: 80, padding: 16, borderBottomWidth: 1, borderColor: '#ccc' }
});

Am văzut prea des scenariul ăsta: o aplicație de React Native începe să aibă lag pe un Android mai vechi și prima reacție a echipei e să pună useMemo și useCallback absolut peste tot. Spoiler: de cele mai multe ori, chestia asta mai mult încurcă. Am avut un proiect anul trecut, o aplicație de e-commerce cu vreo 12.000 de produse în catalog, unde frame-urile pe un Samsung de gamă medie scădeau la 25 FPS la un simplu scroll prin categorii. Am rezolvat problema curățând codul, nu adăugând mai mult.

Mitul useCallback și useMemo

Mulți developeri cred că dacă pun useCallback pe funcția de onPress din interiorul listei, gata, s-a rezolvat performanța. În realitate, useCallback doar salvează referința funcției între randări. Dacă componenta ta copil (să zicem, un card de produs) nu este învelită în React.memo, ea tot se va reranda complet la fiecare modificare din părinte.

Practic, ai adăugat overhead-ul de a rula logica de caching din useCallback absolut degeaba.

Regula mea de aur e simplă: folosește React.memo doar când componenta respectivă se randează des cu aceleași props și randarea ei este costisitoare (are multe sub-componente, calcule de layout sau imagini). Și ai grijă la props: dacă trimiți un array inline style={[styles.card, active && styles.active]}, React.memo va returna mereu false pentru că referința array-ului se schimbă la fiecare randare a părintelui. Folosește StyleSheet.compose sau useMemo pentru acel stil.

Trecerea de la FlatList la FlashList

Pe proiectul de e-commerce de care spuneam, marea schimbare a venit când am înlocuit FlatList din React Native cu FlashList de la Shopify. Am obținut instant 60 FPS stabil pe ecranele de listă lungă.

Cum funcționează? FlatList distruge componentele care ies din ecran și creează altele noi când dai scroll înapoi. Asta pune o presiune uriașă pe CPU și pe bridge-ul de JS. FlashList nu le distruge, ci le reciclează layout-ul (le schimbă doar datele din props).

Trade-off-ul sincer: Nu e totul roz la FlashList

Deși sună ideal, trecerea la FlashList vine cu niște costuri de dezvoltare:

  1. estimatedItemSize: Trebuie să îi dai o valoare cât mai precisă pentru înălțimea medie a unui element. Dacă estimarea e proastă, o să vezi un efect de "jump" foarte deranjant la scroll, deoarece lista recalculează layout-ul din mers.
  2. Starea internă: Dacă item-ul din listă are un useState local (de exemplu, un buton de expandează descrierea), când item-ul este reciclat pentru un alt produs de mai jos, el va păstra starea de expandat. Trebuie să resetezi manual stările locale în funcție de schimbarea id-ului din props.

Pentru liste mici, sub 50-100 de elemente simple, rămâi la FlatList. Complexitatea adăugată de reciclarea componentelor nu merită efortul.

Voi cum abordați optimizarea listelor? Ați trecut complet pe FlashList sau încă mai stoarceți performanță din vechiul FlatList?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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