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

De la 20 la 60 FPS în React Native: Când merită să optimizezi cu memo și FlashList

De Dan Ciobanu, 14 iun. 2026 · 16 vizualizări · 3 like-uri

Postat 14 iun. 2026
javascript
import React, { memo, useCallback } from 'react';
import { Pressable, Text, StyleSheet } from 'react-native';

// Componentă optimizată care nu se va reredera inutil
const ProductItem = memo(({ item, onPress }) => {
  return (
    <Pressable onPress={() => onPress(item.id)} style={styles.card}>
      <Text style={styles.title}>{item.title}</Text>
    </Pressable>
  );
});

// În componenta părinte:
const ParentComponent = () => {
  // useCallback este util aici pentru că trimitem funcția către un element memorat (ProductItem)
  const handlePress = useCallback((id) => {
    console.log('Selected:', id);
  }, []);

  return <ProductItem item={someProduct} onPress={handlePress} />;
};

const styles = StyleSheet.create({
  card: { padding: 16, borderBottomWidth: 1 },
  title: { fontSize: 16, fontWeight: 'bold' }
});

Hai să fim sinceri: majoritatea aplicațiilor React Native merg prost nu din cauza framework-ului, ci pentru că facem optimizări după ureche. Am văzut zeci de codebase-uri unde programatorii au pus useMemo și useCallback peste tot, ca un fel de sos magic, sperând că aplicația o să zboare. Realitatea? Au reușit doar să încarce garbage collector-ul și să facă codul inutil de complex.

Săptămâna trecută am făcut refactoring pe un ecran de feed într-o aplicație cu peste 15.000 de utilizatori activi. Se mișca execrabil pe telefoane de buget. Iată ce am învățat din asta și unde am greșit în trecut.

Mitul useMemo și useCallback

Mulți cred că aceste hook-uri vin pe gratis. Nu e așa. Fiecare useMemo adaugă o mică penalizare de performanță la renderul inițial, pentru că React trebuie să aloce memorie pentru array-ul de dependențe și să facă acele comparații de referință la fiecare ciclu de render.

Regula mea e simplă: folosesc useMemo doar dacă am un calcul cu adevărat greu (cum ar fi filtrarea sau maparea unui array de peste 500 de elemente) sau când rezultatul este folosit ca referință stabilă pentru o componentă copil optimizată cu React.memo.

La fel și la useCallback. Dacă trimiți o funcție direct către un element nativ (cum e un TouchableOpacity sau TextInput), nu câștigi absolut nimic dacă o îmbraci în useCallback. Elementul nativ se va reredera oricum. Folosește-l doar dacă acea funcție merge ca prop într-o componentă custom care folosește React.memo.

Când chiar ajută React.memo?

React.memo previne re-renderizarea unei componente dacă prop-urile nu s-au schimbat. Sună excelent, dar are un cost ascuns: shallow comparison pe obiecte. Dacă trimiți un obiect inline ca prop (de genul style={{ margin: 10 }}), React.memo va returna mereu false pentru că referința obiectului se schimbă la fiecare render al părintelui.

Practic, ai plătit prețul comparației degeaba, iar componenta se reredează oricum. Am avut exact cazul ăsta pe ecranul de feed. După ce am mutat stilurile în StyleSheet.create și am extras funcțiile de navigare în useCallback, React.memo a început în sfârșit să funcționeze. Am redus render-urile inutile cu 70% la scroll.

FlatList vs FlashList: Schimbarea la față

Dacă ai liste lungi sau infinite, FlatList din React Native este, din păcate, destul de limitat. El doar montează și demontează componente pe măsură ce scrollezi. Asta înseamnă un efort uriaș pentru thread-ul de JS, mai ales pe telefoane Android ieftine.

Noi am trecut la FlashList (de la Shopify) pe feed-ul de produse. Diferența a fost colosală. Pe un Android mid-range, frame rate-ul a crescut de la un 25 FPS chinuit la un 60 FPS stabil. Memoria ocupată a scăzut cu vreo 40MB pentru că FlashList reciclează componentele deja create în loc să le distrugă și să le recreeze.

Dar atenție la trade-off-uri. FlashList te obligă să definești un estimatedItemSize. Dacă pui o valoare complet greșită, lista va sări ciudat când dai scroll rapid, pentru că motorul își recalculează greșit layout-ul din mers. Măsoară dimensiunea medie a unui rând înainte să o configurezi.

Tu cum monitorizezi FPS-ul în aplicațiile tale? Te bazezi pe Flipper sau folosești direct profilerele native?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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