découvrez comment optimiser les performances de vos applications react grâce à des techniques efficaces pour accélérer le rendu et améliorer l’expérience utilisateur.

React useMemo ou useCallback : lequel utiliser pour limiter les rendus inutiles ?

Dans React, un composant qui se rend à nouveau n’est pas nécessairement un composant qui pose problème. Les difficultés apparaissent plutôt lorsque ces rendus répètent des calculs coûteux, déclenchent le travail de nombreux composants enfants ou rendent une interface moins réactive. Pour les diagnostiquer, deux hooks reviennent souvent dans les discussions : useMemo, qui conserve une valeur calculée, et useCallback, qui conserve l’identité d’une fonction. Leurs rôles sont proches, mais ils ne répondent pas au même besoin.

Pour une équipe qui construit un tableau de bord, un catalogue ou un éditeur interactif, la différence devient concrète : faut-il stabiliser une fonction transmise à un composant enfant, ou éviter de refaire un tri complexe à chaque mise à jour ? La réponse dépend du coût observé, des dépendances et de la manière dont les composants React sont organisés. Appliquer ces hooks partout ajoute de la complexité sans garantir une optimisation des performances ; les ignorer face à un vrai ralentissement peut aussi laisser une interface inutilement lente.

En bref

  • useMemo mémorise une valeur, par exemple le résultat d’un filtrage ou d’un calcul suffisamment coûteux.

  • useCallback mémorise une référence de fonction, ce qui peut aider lorsqu’elle est transmise à un composant optimisé avec memo.

  • Ni l’un ni l’autre ne bloque à lui seul les rendus inutiles d’un composant.

  • Il faut d’abord repérer le coût réel, puis vérifier l’effet de l’optimisation avec le profileur React.

  • Un état mieux placé et des composants plus simples peuvent être préférables à une multiplication de caches.

Comprendre useMemo et useCallback dans React

Imaginons une boutique en ligne dont le catalogue contient plusieurs milliers de produits. À chaque changement de filtre, la page doit sélectionner les articles correspondants et transmettre des actions aux cartes de produit. Deux opérations distinctes sont en jeu : produire une nouvelle liste et fournir une fonction de sélection. useMemo concerne la première opération ; useCallback concerne la seconde. Cette distinction suffit à éviter une grande partie des confusions autour de la comparaison useMemo et useCallback.

Un composant React s’exécute de nouveau lorsque son état, ses propriétés ou le contexte auquel il est abonné changent. Pendant cette exécution, les expressions ordinaires sont évaluées de nouveau. Ainsi, un filtrage, un tri ou la création d’un objet ont lieu à chaque passage, même si leurs données d’entrée sont identiques. Dans la plupart des interfaces, ces opérations sont suffisamment légères pour ne pas justifier une mémorisation. Le coût dépend du volume de données et du travail effectué, pas du seul fait qu’une ligne de code s’exécute plusieurs fois.

useMemo conserve le résultat d’une fonction de calcul entre des rendus. Il reçoit une fonction et une liste de dépendances ; lorsque ces dépendances restent identiques selon la comparaison utilisée par React, la valeur précédente peut être réutilisée. Dans un catalogue, cela convient par exemple à une liste filtrée à partir des produits, du texte de recherche et des critères sélectionnés. Si l’une de ces entrées change, le calcul est refait afin que l’affichage reste cohérent.

useCallback conserve plutôt l’identité d’une fonction. Il est utile quand cette identité compte pour un autre mécanisme, notamment lorsqu’une fonction est passée en propriété à un enfant enveloppé dans memo. Sans cela, le parent crée une nouvelle fonction à chaque rendu ; React peut alors considérer que la propriété a changé et rendre à nouveau l’enfant. Stabiliser la fonction peut éviter ce passage si les autres propriétés sont également inchangées.

Les deux hooks exigent des dépendances correctes. Omettre une valeur utilisée dans le calcul ou dans la fonction peut produire un résultat obsolète, parce que la version mémorisée continue à se référer à une ancienne donnée. À l’inverse, une dépendance recréée à chaque rendu fait échouer la stabilité recherchée. Il est donc préférable de suivre les règles des hooks et de simplifier les dépendances plutôt que de les retirer artificiellement.

Un détail important : useMemo et useCallback sont des outils d’optimisation, pas des garanties de comportement fonctionnel. Le code doit rester correct même si React recalcule une valeur ou recrée une fonction. La mémorisation sert à réduire du travail évitable ; elle ne doit pas devenir une condition de validité de l’application.

Choisir useMemo pour les calculs coûteux

Dans l’exemple de la boutique, la liste contient un grand nombre d’articles et chaque filtre combine disponibilité, catégorie, prix et pertinence de recherche. Si ce traitement est effectué à chaque rendu du parent, y compris lorsque seul l’état d’un panneau latéral change, il peut devenir une source de latence. C’est dans ce genre de situation que useMemo mérite un essai : il peut réutiliser la liste tant que les produits et les critères employés pour la calculer n’ont pas changé.

La première question n’est toutefois pas « où ajouter useMemo ? », mais « quel travail est réellement coûteux ? ». Une liste de dix éléments filtrée par une condition simple ne justifie généralement pas de cache. À l’inverse, une transformation volumineuse, une agrégation de données ou une préparation complexe de visualisation peut peser dans le temps de rendu. Un profileur permet de repérer les composants lents et de comparer l’interface avant et après une modification, plutôt que de se fier à une impression.

Un exemple simplifié peut être utile. Si un composant reçoit les produits et un texte de recherche, il peut calculer une liste filtrée à partir de ces deux entrées. Le cache doit dépendre des valeurs qui influencent effectivement le résultat : les produits et la recherche, par exemple. Si une dépendance inutile change sans cesse, le calcul repart à chaque rendu ; si une dépendance nécessaire manque, la liste affichée risque de ne plus correspondre aux critères visibles.

Les dépendances de type objet demandent une attention particulière. Une variable créée directement dans le composant, telle qu’un objet d’options, reçoit une nouvelle identité à chaque exécution. Si elle figure dans la liste des dépendances, elle peut annuler le bénéfice du cache. Une solution consiste souvent à construire cet objet à l’intérieur du calcul mémorisé ou à repenser la manière dont les données sont organisées. Il est rarement judicieux d’ajouter un autre hook uniquement pour stabiliser une valeur que l’on peut éviter de créer.

useMemo peut également stabiliser un objet transmis à un enfant optimisé avec memo. Par exemple, des options de graphique calculées à partir de données peuvent être réutilisées tant que ces données ne changent pas. Mais si l’enfant n’est pas mémorisé, ou si une autre propriété change à chaque rendu, cette stabilité ne suffira pas à éviter son exécution. L’avantage doit être évalué dans le contexte de toute la chaîne de composants, pas à partir du hook isolé.

La mémorisation a aussi un coût : elle implique une comparaison des dépendances et rend le code plus difficile à lire si elle est omniprésente. En développement, certains modes peuvent exécuter plusieurs fois certaines logiques pour aider à révéler des effets secondaires ; ce comportement ne doit pas être interprété à lui seul comme une mesure de la performance en production. useMemo est pertinent lorsque le calcul répété a été identifié et que ses entrées peuvent être suivies proprement.

découvrez comment optimiser les performances de vos applications react grâce à des techniques efficaces pour accélérer le rendu et améliorer l’expérience utilisateur.

Utiliser useCallback pour stabiliser les références de fonctions

Dans une interface de catalogue, chaque carte peut proposer un bouton « ajouter aux favoris ». Le parent transmet à chaque carte une fonction qui déclenche cette action. Si cette fonction est recréée à chaque rendu du parent, sa référence change, même si son comportement et les données concernées sont identiques. Lorsque la carte est enveloppée dans memo, cette nouvelle propriété peut suffire à invalider la comparaison et à provoquer un rendu supplémentaire.

useCallback répond précisément à ce cas : il conserve une référence de fonction tant que les dépendances pertinentes ne changent pas. Il peut donc compléter memo lorsque le composant enfant reçoit une fonction en propriété. Pour que l’optimisation soit effective, les autres propriétés de l’enfant doivent elles aussi rester stables. Si le parent lui transmet également un nouvel objet d’options à chaque passage, la stabilisation du gestionnaire ne changera probablement pas le résultat.

Il faut distinguer la stabilité d’une fonction de la réduction automatique des rendus. useCallback ne dit pas à React de ne pas rendre le composant qui le contient. Le composant parent s’exécute toujours lorsque ses propres données changent ; le hook évite seulement de créer une nouvelle identité de fonction dans les conditions prévues. C’est l’interaction avec un composant enfant mémorisé, ou avec une dépendance qui compare les références, qui peut produire un bénéfice visible.

Les dépendances déterminent également les données capturées par la fonction. Si un gestionnaire utilise l’identifiant de l’utilisateur courant, cet identifiant doit être pris en compte afin que la fonction corresponde à l’état le plus récent. Une liste incomplète peut maintenir une ancienne valeur dans la fermeture, créant un bug difficile à repérer : le clic semble fonctionner, mais déclenche une action pour le précédent utilisateur ou sur la précédente sélection.

Pour éviter d’ajouter une dépendance uniquement parce qu’une mise à jour d’état utilise sa valeur précédente, une fonction de mise à jour fonctionnelle peut parfois simplifier le code. Ce choix dépend du cas et doit rester lisible. Il ne s’agit pas de chercher à obtenir la liste de dépendances la plus courte possible, mais de représenter fidèlement les valeurs dont la fonction a besoin.

Une fonction passée à un effet peut aussi nécessiter une réflexion sur sa portée et ses dépendances. Souvent, il est plus simple de déclarer la logique directement dans l’effet plutôt que d’ajouter useCallback par réflexe. La meilleure optimisation peut alors consister à réduire les niveaux d’indirection. useCallback a une valeur lorsque l’identité d’une fonction est observée par un autre composant ou mécanisme ; sinon, son apport est souvent nul.

Comparer les deux hooks et diagnostiquer les rendus inutiles

La comparaison useMemo et useCallback se résume utilement à ce qu’ils mémorisent. Le premier garde une valeur issue d’un calcul ; le second conserve une référence de fonction. Dans la pratique, les deux peuvent participer à la même optimisation : useMemo stabilise des données calculées transmises à un enfant, tandis que useCallback stabilise une action transmise à ce même enfant. Aucun ne remplace memo, et memo ne rend pas automatiquement chaque composant rapide.

Besoin observéOutil à envisagerPoint de vigilance
Un calcul lourd repart sans changement de ses entréesuseMemoDéclarer toutes les dépendances utiles et mesurer le gain
Une fonction passée à un enfant mémorisé change à chaque renduuseCallback, avec memo si appropriéVérifier aussi la stabilité des autres propriétés
Un composant enfant est lent même quand ses propriétés sont stablesProfilage et optimisation localeLa mémorisation des propriétés ne réduit pas le travail interne
L’état d’un petit panneau déclenche le rendu d’une grande pageColocation de l’état ou découpage des composantsÉviter de compenser une architecture trop large par des caches

Un diagnostic méthodique commence par reproduire le ralentissement dans des conditions représentatives. Il faut ensuite déterminer si le temps est consommé dans le composant, dans ses descendants ou dans un calcul particulier. Le profileur de React DevTools aide à visualiser les rendus et leur durée. Une fois le point coûteux identifié, une seule modification à la fois permet de savoir si elle améliore réellement l’expérience.

Considérons une page de rapport où un sélecteur de période actualise une partie du tableau. Si l’ouverture d’une fenêtre de réglages déclenche aussi le recalcul de toutes les lignes, la cause peut être un état placé trop haut dans l’arbre. Déplacer cet état près de la fenêtre peut supprimer des rendus inutiles plus simplement qu’ajouter useMemo à chaque calcul. De même, le découpage en composants réduit parfois la quantité de travail sans introduire de cache supplémentaire.

Les performances perçues comptent autant que les mesures isolées. Une opération peut durer peu de temps dans le profileur, mais se répéter souvent sur un appareil peu puissant ou pendant une interaction fréquente. À l’inverse, un calcul rarement effectué peut ne pas mériter d’optimisation. Il est utile de tester le scénario réel : saisie rapide dans une recherche, changement successif de filtres ou navigation entre plusieurs panneaux.

La stabilité des propriétés prend tout son sens avec memo. Ce dernier compare les propriétés pour déterminer si un rendu peut être évité ; une fonction ou un objet fraîchement créé peut rendre cette comparaison négative. La solution n’est pas de mémoriser systématiquement tout ce qui traverse l’arbre, mais de s’assurer que la comparaison coûte moins cher que le travail évité et que le code reste facile à maintenir. Mesurer d’abord, optimiser ensuite : c’est le moyen le plus fiable de distinguer un vrai problème d’un simple soupçon.

Construire une stratégie d’optimisation durable pour les composants React

Dans une application qui évolue, l’optimisation des performances ne se limite pas à choisir entre deux hooks. Une équipe peut commencer par observer les interactions les plus importantes, puis repérer les composants rendus à répétition et les calculs qui prennent une part notable du temps. Cette démarche évite de transformer chaque composant React en réseau de dépendances mémorisées, difficile à relire pour les personnes qui maintiennent le produit.

Le placement de l’état est un levier souvent sous-estimé. Si un état ne concerne qu’un formulaire ou un menu, le conserver dans le composant correspondant évite de faire remonter ses mises à jour à toute une page. Pour les états partagés, il est utile de choisir une organisation adaptée au besoin, plutôt que de diffuser inutilement des valeurs dans une grande arborescence. Un guide sur la gestion d’état simplifiée avec Zustand dans React peut aider à comparer les options d’organisation lorsque plusieurs composants doivent accéder aux mêmes données.

Context API peut également convenir à certaines valeurs partagées, mais chaque changement d’un contexte peut mettre à jour les consommateurs concernés. Il est donc pertinent de réfléchir à la granularité des contextes et aux composants qui s’y abonnent. L’article consacré à la gestion de l’état global avec Context API apporte un angle complémentaire : la structure des données et leur diffusion influencent les mises à jour autant que les hooks de mémorisation.

Pour une équipe, une règle de revue simple peut éviter les optimisations préventives. Lorsqu’un hook est ajouté, la personne qui propose le changement peut préciser quel rendu ou calcul a été mesuré, quelle dépendance déclenche le travail, et quel résultat est attendu. Après modification, le même scénario doit être testé. Cette pratique transforme la mémorisation en décision vérifiable, plutôt qu’en convention appliquée par habitude.

Il faut aussi garder à l’esprit l’évolution de l’écosystème React et des outils de compilation. Selon le projet et la configuration, certains outils peuvent automatiser une partie des optimisations. Cela ne dispense pas de comprendre le coût des composants, les effets des dépendances ou la structure de l’état. Les choix automatiques ne remplacent ni les tests fonctionnels ni l’analyse d’une interaction réellement lente.

Enfin, une interface fluide ne dépend pas uniquement du nombre de rendus. La quantité de données affichées, la complexité du DOM et le travail du navigateur peuvent compter autant. Un catalogue contenant des milliers de lignes peut nécessiter une stratégie de virtualisation, tandis qu’une page riche en images doit traiter le chargement et le poids des ressources. Les hooks sont des outils ciblés au sein d’une stratégie plus large, pas une réponse universelle à tout ralentissement.

La règle de décision reste donc pratique : useMemo pour réutiliser un résultat calculé, useCallback pour préserver une référence de fonction lorsque cette identité est utile. Quand les rendus inutiles viennent d’un état trop haut ou d’un composant trop large, revoir l’architecture peut apporter davantage qu’une couche de mémorisation.

Questions fréquentes sur useMemo et useCallback

{« @context »: »https://schema.org », »@type »: »FAQPage », »mainEntity »:[{« @type »: »Question », »name »: »useMemo empu00eache-t-il un composant de se rendre u00e0 nouveau ? », »acceptedAnswer »:{« @type »: »Answer », »text »: »Non. Le composant qui appelle useMemo peut toujours u00eatre rendu. Le hook peut u00e9viter de recalculer une valeur lorsque ses du00e9pendances nu2019ont pas changu00e9, mais il ne bloque pas u00e0 lui seul le rendu du composant. »}},{« @type »: »Question », »name »: »Peut-on utiliser useCallback u00e0 la place de useMemo ? », »acceptedAnswer »:{« @type »: »Answer », »text »: »Pas pour conserver directement le ru00e9sultat du2019un calcul. useCallback conserve une ru00e9fu00e9rence de fonction, tandis que useMemo conserve une valeur calculu00e9e. Leur emploi du00e9pend donc de la donnu00e9e que lu2019on veut stabiliser. »}},{« @type »: »Question », »name »: »Faut-il ajouter useMemo et useCallback partout ? », »acceptedAnswer »:{« @type »: »Answer », »text »: »Non. Chaque hook ajoute une logique de du00e9pendances et un cou00fbt de comparaison. Il vaut mieux les utiliser apru00e8s avoir identifiu00e9 un calcul cou00fbteux ou une ru00e9fu00e9rence instable qui provoque un travail mesurable. »}},{« @type »: »Question », »name »: »Pourquoi un composant mu00e9morisu00e9 se rend-il encore ? », »acceptedAnswer »:{« @type »: »Answer », »text »: »memo compare les propriu00e9tu00e9s, mais un changement de propriu00e9tu00e9, du2019u00e9tat local ou de contexte peut toujours du00e9clencher un rendu. Une fonction ou un objet recru00e9u00e9 u00e0 chaque passage peut u00e9galement faire u00e9chouer la comparaison des propriu00e9tu00e9s. »}}]}

useMemo empêche-t-il un composant de se rendre à nouveau ?

Non. Le composant qui appelle useMemo peut toujours être rendu. Le hook peut éviter de recalculer une valeur lorsque ses dépendances n’ont pas changé, mais il ne bloque pas à lui seul le rendu du composant.

Peut-on utiliser useCallback à la place de useMemo ?

Pas pour conserver directement le résultat d’un calcul. useCallback conserve une référence de fonction, tandis que useMemo conserve une valeur calculée. Leur emploi dépend donc de la donnée que l’on veut stabiliser.

Faut-il ajouter useMemo et useCallback partout ?

Non. Chaque hook ajoute une logique de dépendances et un coût de comparaison. Il vaut mieux les utiliser après avoir identifié un calcul coûteux ou une référence instable qui provoque un travail mesurable.

Pourquoi un composant mémorisé se rend-il encore ?

memo compare les propriétés, mais un changement de propriété, d’état local ou de contexte peut toujours déclencher un rendu. Une fonction ou un objet recréé à chaque passage peut également faire échouer la comparaison des propriétés.

Publications similaires

  • Utiliser Supabase comme alternative open-source à Firebase

    Dans le monde du développement d’applications, Firebase de Google est souvent la solution tout-en-un privilégiée, proposant une multitude de services intégrés. Cependant, l’attrait pour des alternatives open-source comme Supabase est en forte croissance, car ces solutions offrent une flexibilité et un contrôle accrus sur l’infrastructure. Avec ses fonctionnalités robustes basées sur PostgreSQL, Supabase permet aux…

  • Configurer les redirections 301 avec .htaccess

    Dans le domaine du développement web, la gestion des redirections 301 est essentielle pour maintenir l’intégrité et la performance d’un site. Ces redirections permanentes permettent de signaler aux moteurs de recherche et aux utilisateurs qu’une page a été déplacée vers une nouvelle URL. L’implémentation de ces redirections se fait souvent à travers le fichier .htaccess,…

  • Réussir son créneau en marche arrière sans stress

    Le créneau en marche arrière est l’une des manœuvres les plus redoutées par de nombreux conducteurs, qu’ils soient jeunes permis ou expérimentés. Cette opération, souvent associée à une certaine complexité et au stress des regards extérieurs, est pourtant indispensable en milieu urbain et représente un passage obligé lors de l’examen du permis de conduire. Heureusement,…

  • Quelle différence entre Google Tag Manager et Matomo pour le suivi analytics ?

    Le suivi analytics est un élément clé pour toute stratégie digitale réussie. Entre Google Tag Manager et Matomo, deux solutions souvent évoquées, nombreux sont ceux qui cherchent à comprendre non seulement leurs différences mais également leurs complémentarités et cas d’usage spécifiques. Ces outils, bien que destinés à collecter et organiser les données utilisateurs, offrent des…