A useMemo hook a React Native-ban memoizálja a számítások eredményét a komponens renderelései között, megakadályozva a költséges műveletek ismételt végrehajtását. Ellentétben a useCallback-lel, amely a függvényt memoizálja, a useMemo a visszaadott értéket tárolja, és csak akkor számolja újra, ha a megadott függőségek megváltoznak. A React Docs, 2024 szerint a memoizáció különösen hatékony nagy méretű tömbökkel végzett számítások és összetett adatátalakítások esetén. A React Native-ban minden további újrarenderelés további terhelést jelent a JavaScript és a natív szálak közötti híd kapcsolaton, ezért a useMemo helyes használata közvetlenül befolyásolja az animációk simaságát és a felület válaszidejét.
Fő pontok
useMemo — egy hook a React szabványos könyvtárából, amely a React Native-ban elérhető további csomagok nélkül. Memoizálja az átadott függvény által visszaadott értéket, és ezt az értéket használja fel a következő renderelések során, amíg a tömbben megadott függőségek meg nem változnak.
A hook neve az angol memoization szóból származik — egy optimalizációs technika, amely során egy költséges függvény eredményét gyorsítótárban tároljuk. Ismételt hívás esetén ugyanazokkal az argumentumokkal a tárolt érték kerül visszaadásra az újraszámítás helyett.
A React Native kontextusában a memoizáció különösen fontos az architektúra miatt. A komponens minden újrarenderelése adatokat küld a JavaScript — Natív hídon keresztül, ami időt vesz igénybe. Ha a komponens költséges számításokat tartalmaz (lista szűrése, rendezése, formázása), minden újrarenderelés megismétli azokat, blokkolva a JS szálat és képkocka kiesést okozva.
A React Native Performance Docs, 2024 szerint a szűk keresztmetszet gyakran nem a natív komponensek renderelése, hanem a JavaScript logika végrehajtása a renderelések között. A useMemo pontosan ezt a problémát oldja meg.
useMemo fogad egy függvényt és egy függőségi tömböt, és visszaad egy memoizált értéket. A React tárolja az előző értéket és a függőségi tömböt. Minden rendereléskor a React összehasonlítja az aktuális függőségeket az előzőekkel a Object.is segítségével. Ha legalább egy függőség megváltozott, a függvény újra végrehajtódik, és az eredmény eltárolódik.
A useMemo aláírása teljesen azonos a weben és a React Native-ban. Az első argumentum — egy paraméter nélküli függvény, amely a memoizálandó értéket adja vissza. A második — a függőségi tömb, amelynek változásakor az érték újraszámításra kerül.
import React, { useMemo } from 'react';
const sortedList = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
Ebben a példában a sortedList csak akkor számolódik újra, ha az items tömb referenciája megváltozik. Ha a tömb tartalmilag változott, de a referencia ugyanaz maradt (mutáció), a useMemo nem fogja észlelni a változásokat — ez egy fontos korlátozás.
A React a függőségek összehasonlításához a Object.is algoritmust használja, amely hasonlóan működik a szigorú egyenlőséghez ===, de helyesen kezeli a NaN-t (+0 és -0 különbözőnek számít). Ez azt jelenti, hogy primitív típusok (karakterláncok, számok, logikai értékek) esetén az összehasonlítás érték alapján, objektumok és tömbök esetén pedig referencia alapján működik.
// Object.is({'a': 1}, {'a': 1}) -> false (különböző referenciák)
// Object.is(42, 42) -> true (primitív érték alapján)
// Object.is(NaN, NaN) -> true (NaN helyes kezelése)
Ennek a mechanizmusnak a megértése kritikus: ha minden rendereléskor egy új objektumot adsz át a függőségekben, a memoizáció haszontalan lesz, mert a függőségek minden alkalommal megváltozottnak minősülnek.
useMemo három esetben indokolt: költséges számítások, stabil prop-ok átadása gyermek komponenseknek, és objektumok referenciális azonosságának megőrzése. React Native-ban mindhárom eset rendszeresen előfordul a mobilalkalmazások architektúrájának sajátosságai miatt.
Ha a komponens nagy adattömbök feldolgozását (szűrés, rendezés, csoportosítás) vagy erőforrás-igényes matematikai műveleteket végez, a useMemo megakadályozza ezen számítások megismétlődését minden újrarendereléskor. Mobilalkalmazásokban tipikus példa az API-ból érkező adatok formázása a listában való megjelenítés előtt.
Amikor a gyermek komponens React.memo-ba van csomagolva, csak a prop-ok változásakor renderelődik újra. Ha a prop objektum a szülőn belül useMemo nélkül jön létre, minden szülő rendereléskor új referencia jön létre, és a gyermek komponens újrarenderelődik, semmissé téve a React.memo előnyét.
React Native-ban a stílusok gyakran függnek a prop-októl — például egy elem szélessége a képernyő mérete alapján kerül kiszámításra. A useMemo lehetővé teszi az ilyen dinamikus stílusok kiszámítását csak a bemeneti paraméterek változásakor.
useMemo nem egy univerzális optimalizációs eszköz. Bizonyos esetekben nem hoz előnyt, sőt ronthatja a teljesítményt a függőségek tárolásának és összehasonlításának többletköltsége miatt. React Native-ban, ahol minden bájt memória számít, a useMemo vak alkalmazása a hatás mérése nélkül anti-minta.
A hook három fő esetben nem hoz hasznot. Először is, ha a számítás triviális (egyszerű összeadás, karakterlánc-összefűzés), a useMemo költségei meghaladják magának a számításnak az értékét. Másodszor, ha a függőségek minden rendereléskor változnak — a függvény akkor is végrehajtódik, a memoizáció pedig csak plusz munkát ad hozzá. Harmadszor, ha a komponens ritkán renderelődik, a gyorsítótár tárolásának többletköltsége nem indokolt.
A Kent C. Dodds, 2023 szerint a useMemo hozzáadása előtt meg kell mérni a problémát a React DevTools Profiler vagy a React Native beépített Performance Monitor segítségével. Ha a komponens újrarenderelése kevesebb mint 1 ms-ig tart, a memoizáció nem szükséges.
useMemo és useCallback — két memoizációs hook a React-ből, amelyeket gyakran összekevernek. A különbség abban rejlik, hogy mit tárolnak: a useMemo a függvény végrehajtásának eredményét adja vissza (bármilyen értéket), míg a useCallback magát a függvényt adja vissza. Mindkettő fogad egy függőségi tömböt, de a szintaxis eltér.
| Jellemző | useMemo | useCallback |
|---|---|---|
| Visszaad | Függvény végrehajtásának eredménye | Referencia a függvényre |
| Első argumentum | Függvény, amely értéket ad vissza | Memoizálandó függvény |
| Tipikus használat | Számítások gyorsítótárazása | Stabil callback-ek gyermek komponensekhez |
| Ekvivalencia | useMemo(() => fn, deps) | useCallback(fn, deps) === useMemo(() => fn, deps) |
A gyakorlatban a useCallback szintaktikai cukor a useMemo felett arra az esetre, amikor egy függvényt kell memoizálni. React Native-ban mindkét hook-ot egyforma gyakran használják: useMemo — adatokhoz (formázott szöveg, kiszámított stílusok), useCallback — eseménykezelőkhöz (onPress, onChangeText).
Vizsgáljunk meg két valós forgatókönyvet a useMemo használatára React Native alkalmazásokban. Az első — névjegyzék szűrése keresési lekérdezés alapján, a második — dinamikus stílusok kiszámítása a képernyő mérete alapján.
Ebben a példában a useMemo megakadályozza a nagy névjegyzék ismételt szűrését minden rendereléskor, ha sem a keresési lekérdezés, sem a forrásadatok nem változtak.
const ContactList = ({ contacts, searchQuery }) => {
const filteredContacts = useMemo(() => {
if (!searchQuery.trim()) return contacts;
const query = searchQuery.toLowerCase();
return contacts.filter((c) =>
c.name.toLowerCase().includes(query) ||
c.phone.includes(query)
);
}, [contacts, searchQuery]);
return (
<FlatList
data={filteredContacts}
renderItem={renderContact}
keyExtractor={(item) => item.id}
/>
);
};
UseMemo nélkül a szűrés minden rendereléskor végrehajtódna, beleértve az animációk vagy a komponens más részeinek állapotváltozásai által okozott rendereléseket is. A useMemo-val a szűrés csak a contacts vagy a searchQuery változásakor indul el.
React Native-ban a stílusok gyakran függnek a képernyő méretétől vagy a komponens prop-jaitól. A useMemo lehetővé teszi egy ilyen stílus objektum egyszeri kiszámítását és újrafelhasználását, amíg a függőségek meg nem változnak.
const Card = ({ title, isSelected }) => {
const cardStyle = useMemo(() => ({
backgroundColor: isSelected ? '#e3f2fd' : '#ffffff',
borderWidth: isSelected ? 2 : 1,
padding: 16,
}), [isSelected]);
return (
<View style={cardStyle}>
<Text>{title}</Text>
</View>
);
};
Ez a megközelítés garantálja, hogy a cardStyle objektum stabil marad (ugyanaz a referencia), amíg az isSelected meg nem változik. Ha a Card React.memo-ba van csomagolva, ez a minta megakadályozza a gyermek elemek szükségtelen újrarenderelését.
Gyakran ismételt kérdések
A useMemo a memoizált értéket adja vissza — az első argumentumként átadott függvény végrehajtásának eredményét. A következő renderelések során a React a tárolt értéket adja vissza, ha a függőségek nem változtak.
A useMemo a függvény végrehajtásának eredményét adja vissza (bármilyen értéket: számot, objektumot, JSX-et), míg a useCallback magát a függvényt adja vissza. Emellett a useCallback(fn, deps) egyenértékű a useMemo(() => fn, deps) kifejezéssel.
A useMemo haszontalan triviális számításoknál (összeadás, összefűzés), ritka újrarendereléseknél, minden rendereléskor változó függőségeknél és primitív típusoknál. Mindig mérd meg a teljesítményt a useMemo hozzáadása előtt.
Igen, ha szükségtelenül használjuk. A React tárolja az előző értékeket a memóriában, és minden rendereléskor elvégzi a függőségek összehasonlítását. Egyszerű számítások esetén ezen műveletek többletköltsége meghaladja a memoizáció előnyét.
Használd a React DevTools Profiler-t a komponensek renderelési idejének mérésére. React Native-ban a Performance Monitor is elérhető a fejlesztői menün keresztül. Ha az újrarenderelés kevesebb mint 1 ms-ig tart — a useMemo nem szükséges.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is