Le hook useMemo dans React Native mémoïse le résultat des calculs entre les rendus de composants, empêchant l'exécution répétée d'opérations coûteuses. Contrairement à useCallback qui mémoïse une fonction, useMemo conserve la valeur retournée et la recalcule uniquement lorsque les dépendances spécifiées changent. Selon React Docs, 2024, la mémoïsation est particulièrement efficace pour les calculs avec de grands tableaux et des transformations de données complexes. Dans React Native, chaque rendu inutile crée une charge supplémentaire sur la connexion pont entre JavaScript et les threads natifs, donc une utilisation correcte de useMemo affecte directement la fluidité des animations et la vitesse de réponse de l'interface.
Points clés
useMemo — est un hook de la bibliothèque standard de React, disponible dans React Native sans paquets supplémentaires. Il mémoïse la valeur retournée par la fonction passée et réutilise cette valeur lors des rendus suivants jusqu'à ce que les dépendances spécifiées dans le tableau changent.
Le nom du hook vient de memoization — une technique d'optimisation où le résultat d'une fonction coûteuse est stocké dans un cache. Lors des appels ultérieurs avec les mêmes arguments, la valeur mise en cache est retournée au lieu d'être recalculée.
Dans le contexte de React Native, la mémoïsation est particulièrement importante en raison des caractéristiques architecturales. Chaque rendu de composant envoie des données via le pont JavaScript — Natif, ce qui prend du temps. Si un composant contient des calculs coûteux (filtrage de liste, tri, formatage), chaque rendu les répétera, bloquant le thread JS et provoquant des chutes d'images.
Selon React Native Performance Docs, 2024, le goulot d'étranglement n'est souvent pas le rendu des composants natifs, mais l'exécution de la logique JavaScript entre les rendus. useMemo résolve précisément ce problème.
useMemo prend une fonction et un tableau de dépendances, retournant une valeur mémoïsée. React stocke la valeur précédente et le tableau de dépendances. À chaque rendu, React compare les dépendances actuelles avec les précédentes en utilisant Object.is. Si au moins une dépendance a changé, la fonction est exécutée à nouveau et le résultat est stocké.
La signature de useMemo est identique sur le web et dans React Native. Le premier argument est une fonction sans paramètres qui retourne la valeur à mémoïser. Le second est un tableau de dépendances, dont les changements entraîneront le recalcul de la valeur.
import React, { useMemo } from 'react';
const sortedList = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
Dans cet exemple, sortedList est recalculé uniquement lorsque la référence au tableau items change. Si le contenu du tableau a changé mais que la référence est restée la même (mutation), useMemo ne détectera pas les changements — c'est une limitation importante.
React utilise l'algorithme Object.is pour comparer les dépendances, qui fonctionne de manière similaire à l'égalité stricte === mais traite NaN correctement (+0 et -0 sont considérés comme différents). Cela signifie que pour les types primitifs (chaînes, nombres, booléens), la comparaison fonctionne par valeur, tandis que pour les objets et les tableaux — par référence.
// Object.is({'a': 1}, {'a': 1}) -> false (different refs)
// Object.is(42, 42) -> true (primitive by value)
// Object.is(NaN, NaN) -> true (correct handling of NaN)
Comprendre ce mécanisme est crucial : si vous passez un nouvel objet dans les dépendances à chaque rendu, la mémoïsation sera inutile car les dépendances seront considérées comme modifiées à chaque fois.
useMemo est justifié dans trois scénarios : les calculs coûteux, le passage de props stables aux composants enfants et la préservation de l'identité référentielle des objets. Dans React Native, les trois scénarios se produisent régulièrement en raison de l'architecture des applications mobiles.
Si un composant traite de grands tableaux de données (filtrage, tri, regroupement) ou des opérations mathématiques intensives, useMemo évite de répéter ces calculs à chaque rendu. Dans les applications mobiles, un exemple typique est le formatage des données d'une API avant de les afficher dans une liste.
Lorsqu'un composant enfant est enveloppé dans React.memo, il ne se rend à nouveau que lorsque ses props changent. Si un objet prop est créé à l'intérieur du parent sans useMemo, une nouvelle référence sera créée à chaque rendu du parent, et le composant enfant se rendra inutilement, annulant le bénéfice de React.memo.
Dans React Native, les styles dépendent souvent des props — par exemple, la largeur d'un élément est calculée en fonction de la taille de l'écran. useMemo permet de calculer ces styles dynamiques uniquement lorsque les paramètres d'entrée changent.
useMemo n'est pas un outil d'optimisation universel. Dans plusieurs scénarios, il n'apporte aucun bénéfice et peut même dégrader les performances en raison de la surcharge de stockage et de comparaison des dépendances. Dans React Native, où chaque octet de mémoire compte, appliquer useMemo aveuglément sans mesurer son effet est un anti-modèle.
Le hook n'apporte aucun bénéfice dans trois cas principaux. Premièrement, si le calcul est trivial (addition simple, concaténation de chaînes), le coût de useMemo dépasse le coût du calcul lui-même. Deuxièmement, si les dépendances changent à chaque rendu — la fonction sera quand même exécutée, et la mémoïsation ajoute seulement du travail supplémentaire. Troisièmement, si le composant se rend rarement, la surcharge de stockage en cache n'est pas justifiée.
Selon Kent C. Dodds, 2023, avant d'ajouter useMemo, vous devez mesurer le problème en utilisant React DevTools Profiler ou le Moniteur de Performances intégré dans React Native. Si le rendu d'un composant prend moins de 1 ms, la mémoïsation n'est pas nécessaire.
useMemo et useCallback — deux hooks de mémoïsation de React qui sont souvent confondus. La différence réside dans ce qu'ils préservent : useMemo retourne le résultat de l'exécution d'une fonction (n'importe quelle valeur), tandis que useCallback retourne la fonction elle-même. Les deux acceptent un tableau de dépendances, mais la syntaxe diffère.
| Caractéristique | useMemo | useCallback |
|---|---|---|
| Retourne | Résultat de l'exécution de la fonction | Référence à la fonction |
| Premier argument | Fonction retournant une valeur | Fonction à mémoïser |
| Utilisation typique | Mise en cache des calculs | Callbacks stables pour les composants enfants |
| Équivalence | useMemo(() => fn, deps) | useCallback(fn, deps) === useMemo(() => fn, deps) |
En pratique, useCallback est du sucre syntaxique sur useMemo pour les cas où vous devez mémoïser une fonction. Dans React Native, les deux hooks sont utilisés aussi fréquemment : useMemo — pour les données (texte formaté, styles calculés), useCallback — pour les gestionnaires d'événements (onPress, onChangeText).
Examinons deux scénarios réels d'utilisation de useMemo dans les applications React Native. Le premier est le filtrage d'une liste de contacts par requête de recherche, le second est le calcul de styles dynamiques basés sur la taille de l'écran.
Dans cet exemple, useMemo empêche le filtrage répété d'une grande liste de contacts à chaque rendu si ni la requête de recherche ni les données sources n'ont changé.
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}
/>
);
};
Sans useMemo, le filtrage s'exécuterait à chaque rendu, y compris ceux provoqués par des animations ou des changements d'état dans d'autres parties du composant. Avec useMemo, le filtrage s'exécute uniquement lorsque contacts ou searchQuery changent.
Dans React Native, les styles dépendent souvent des dimensions de l'écran ou des props du composant. useMemo permet de calculer cet objet de styles une fois et de le réutiliser jusqu'à ce que les dépendances changent.
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>
);
};
Cette approche garantit que l'objet cardStyle reste stable (même référence) jusqu'à ce que isSelected change. Si Card est enveloppé dans React.memo, ce modèle évite les rendus inutiles des éléments enfants.
Questions fréquentes
useMemo retourne une valeur mémoïsée — le résultat de l'exécution de la fonction passée comme premier argument. Lors des rendus suivants, React retourne la valeur mise en cache si les dépendances n'ont pas changé.
useMemo retourne le résultat de l'exécution de la fonction (n'importe quelle valeur : nombre, objet, JSX), tandis que useCallback retourne la fonction elle-même. Notez que useCallback(fn, deps) est équivalent à useMemo(() => fn, deps).
useMemo est inutile pour les calculs triviaux (addition, concaténation), les rendus rares, les dépendances qui changent à chaque rendu et les types primitifs. Mesurez toujours les performances avant d'ajouter useMemo.
Oui, s'il est utilisé inutilement. React stocke les valeurs précédentes en mémoire et compare les dépendances à chaque rendu. Pour les calculs simples, la surcharge de ces opérations dépasse le bénéfice de la mémoïsation.
Utilisez React DevTools Profiler pour mesurer les temps de rendu des composants. Dans React Native, le Moniteur de Performances est également disponible via le menu développeur. Si un rendu prend moins de 1 ms — useMemo n'est pas nécessaire.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi