Français

Explorez les techniques avancées de mémoïsation React pour optimiser les performances dans les applications globales. Découvrez quand et comment utiliser React.memo, useCallback, useMemo, etc. pour créer des interfaces utilisateur efficaces.

React Memo : Exploration approfondie des techniques d’optimisation pour les applications globales

React est une puissante bibliothèque JavaScript pour créer des interfaces utilisateur, mais à mesure que les applications gagnent en complexité, l’optimisation des performances devient cruciale. Un outil essentiel dans la boîte à outils d’optimisation React est React.memo. Cet article de blog fournit un guide complet pour comprendre et utiliser efficacement React.memo et les techniques connexes afin de créer des applications React hautes performances pour un public mondial.

Qu’est-ce que React.memo ?

React.memo est un composant d’ordre supérieur (HOC) qui mémoïse un composant fonctionnel. En termes plus simples, il empêche un composant d’être rendu à nouveau si ses props n’ont pas changé. Par défaut, il effectue une comparaison superficielle des props. Cela peut considérablement améliorer les performances, en particulier pour les composants dont le rendu est coûteux en calcul ou qui sont rendus à nouveau fréquemment même lorsque leurs props restent les mêmes.

Imaginez un composant affichant le profil d’un utilisateur. Si les informations de l’utilisateur (par exemple, le nom, l’avatar) n’ont pas changé, il n’est pas nécessaire de rendre à nouveau le composant. React.memo vous permet d’ignorer ce nouveau rendu inutile, ce qui permet d’économiser un temps de traitement précieux.

Pourquoi utiliser React.memo ?

Voici les principaux avantages de l’utilisation de React.memo :

Utilisation de base de React.memo

L’utilisation de React.memo est simple. Il suffit d’encapsuler votre composant fonctionnel avec celui-ci :

import React from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data}
); }; export default React.memo(MyComponent);

Dans cet exemple, MyComponent ne sera rendu à nouveau que si la prop data change. L’instruction console.log vous aidera à vérifier quand le composant est réellement rendu à nouveau.

Comprendre la comparaison superficielle

Par défaut, React.memo effectue une comparaison superficielle des props. Cela signifie qu’il vérifie si les références aux props ont changé, et non les valeurs elles-mêmes. Il est important de le comprendre lorsque vous travaillez avec des objets et des tableaux.

Considérez l’exemple suivant :

import React, { useState } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data.name}
); }; const MemoizedComponent = React.memo(MyComponent); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); // Creating a new object with the same values }; return (
); }; export default App;

Dans ce cas, même si les valeurs de l’objet user (name et age) restent les mêmes, la fonction handleClick crée une nouvelle référence d’objet chaque fois qu’elle est appelée. Par conséquent, React.memo verra que la prop data a changé (car la référence d’objet est différente) et rendra à nouveau MyComponent.

Fonction de comparaison personnalisée

Pour résoudre le problème de la comparaison superficielle avec les objets et les tableaux, React.memo vous permet de fournir une fonction de comparaison personnalisée comme deuxième argument. Cette fonction prend deux arguments : prevProps et nextProps. Elle doit renvoyer true si le composant ne doit *pas* être rendu à nouveau (c’est-à-dire que les props sont effectivement les mêmes) et false s’il doit être rendu à nouveau.

Voici comment vous pouvez utiliser une fonction de comparaison personnalisée dans l’exemple précédent :

import React, { useState, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data.name}
); }; const areEqual = (prevProps, nextProps) => { return prevProps.data.name === nextProps.data.name && prevProps.data.age === nextProps.data.age; }; const MemoizedComponent = memo(MyComponent, areEqual); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); }; return (
); }; export default App;

Dans cet exemple mis à jour, la fonction areEqual compare les propriétés name et age des objets user. Le MemoizedComponent ne sera rendu à nouveau que si name ou age change.

Quand utiliser React.memo

React.memo est plus efficace dans les scénarios suivants :

Toutefois, il est important de noter que React.memo n’est pas une panacée. L’utiliser sans discernement peut en fait nuire aux performances, car la comparaison superficielle elle-même a un coût. Par conséquent, il est essentiel de profiler votre application et d’identifier les composants qui bénéficieraient le plus de la mémoïsation.

Alternatives à React.memo

Bien que React.memo soit un outil puissant, ce n’est pas la seule option pour optimiser les performances des composants React. Voici quelques alternatives et techniques complémentaires :

1. PureComponent

Pour les composants de classe, PureComponent offre une fonctionnalité similaire à React.memo. Il effectue une comparaison superficielle des props et de l’état, et n’est rendu à nouveau qu’en cas de changement.

import React from 'react';

class MyComponent extends React.PureComponent {
 render() {
 console.log('MyComponent rendered');
 return (
 
{this.props.data}
); } } export default MyComponent;

PureComponent est une alternative pratique à l’implémentation manuelle de shouldComponentUpdate, qui était la façon traditionnelle d’empêcher les nouveaux rendus inutiles dans les composants de classe.

2. shouldComponentUpdate

shouldComponentUpdate est une méthode de cycle de vie dans les composants de classe qui vous permet de définir une logique personnalisée pour déterminer si un composant doit être rendu à nouveau. Elle offre la plus grande flexibilité, mais elle nécessite également plus d’efforts manuels.

import React from 'react';

class MyComponent extends React.Component {
 shouldComponentUpdate(nextProps, nextState) {
 return nextProps.data !== this.props.data;
 }

 render() {
 console.log('MyComponent rendered');
 return (
 
{this.props.data}
); } } export default MyComponent;

Bien que shouldComponentUpdate soit toujours disponible, PureComponent et React.memo sont généralement préférés pour leur simplicité et leur facilité d’utilisation.

3. useCallback

useCallback est un hook React qui mémoïse une fonction. Il renvoie une version mémoïsée de la fonction qui ne change que si l’une de ses dépendances a changé. Ceci est particulièrement utile pour transmettre des rappels en tant que props aux composants mémoïsés.

Considérez l’exemple suivant :

import React, { useState, useCallback, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
 );
};

const MemoizedComponent = memo(MyComponent);

const App = () => {
 const [count, setCount] = useState(0);

 const handleClick = useCallback(() => {
 setCount(count + 1);
 }, [count]);

 return (
 

Count: {count}

); }; export default App;

Dans cet exemple, useCallback garantit que la fonction handleClick ne change que lorsque l’état count change. Sans useCallback, une nouvelle fonction serait créée à chaque rendu de App, ce qui entraînerait le rendu à nouveau inutile de MemoizedComponent.

4. useMemo

useMemo est un hook React qui mémoïse une valeur. Il renvoie une valeur mémoïsée qui ne change que si l’une de ses dépendances a changé. Ceci est utile pour éviter les calculs coûteux qui n’ont pas besoin d’être réexécutés à chaque rendu.

import React, { useState, useMemo } from 'react';

const App = () => {
 const [input, setInput] = useState('');

 const expensiveCalculation = (str) => {
 console.log('Calculating...');
 let result = 0;
 for (let i = 0; i < str.length * 1000000; i++) {
 result++;
 }
 return result;
 };

 const memoizedResult = useMemo(() => expensiveCalculation(input), [input]);

 return (
 
setInput(e.target.value)} />

Result: {memoizedResult}

); }; export default App;

Dans cet exemple, useMemo garantit que la fonction expensiveCalculation n’est appelée que lorsque l’état input change. Cela empêche le calcul d’être réexécuté à chaque rendu, ce qui peut considérablement améliorer les performances.

Exemples pratiques pour les applications globales

Considérons quelques exemples pratiques de la façon dont React.memo et les techniques connexes peuvent être appliqués dans les applications globales :

1. Sélecteur de langue

Un composant de sélecteur de langue rend souvent une liste des langues disponibles. La liste peut être relativement statique, ce qui signifie qu’elle ne change pas fréquemment. L’utilisation de React.memo peut empêcher le sélecteur de langue d’être rendu à nouveau inutilement lorsque d’autres parties de l’application sont mises à jour.

import React, { memo } from 'react';

const LanguageItem = ({ language, onSelect }) => {
 console.log(`LanguageItem ${language} rendered`);
 return (
 
  • onSelect(language)}>{language}
  • ); }; const MemoizedLanguageItem = memo(LanguageItem); const LanguageSelector = ({ languages, onSelect }) => { return (
      {languages.map((language) => ( ))}
    ); }; export default LanguageSelector;

    Dans cet exemple, MemoizedLanguageItem ne sera rendu à nouveau que si la prop language ou onSelect change. Cela peut être particulièrement bénéfique si la liste des langues est longue ou si le gestionnaire onSelect est complexe.

    2. Convertisseur de devises

    Un composant de convertisseur de devises peut afficher une liste de devises et leurs taux de change. Les taux de change peuvent être mis à jour périodiquement, mais la liste des devises peut rester relativement stable. L’utilisation de React.memo peut empêcher la liste des devises d’être rendue à nouveau inutilement lorsque les taux de change sont mis à jour.

    import React, { memo } from 'react';
    
    const CurrencyItem = ({ currency, rate, onSelect }) => {
     console.log(`CurrencyItem ${currency} rendered`);
     return (
     
  • onSelect(currency)}>{currency} - {rate}
  • ); }; const MemoizedCurrencyItem = memo(CurrencyItem); const CurrencyConverter = ({ currencies, onSelect }) => { return (
      {Object.entries(currencies).map(([currency, rate]) => ( ))}
    ); }; export default CurrencyConverter;

    Dans cet exemple, MemoizedCurrencyItem ne sera rendu à nouveau que si la prop currency, rate ou onSelect change. Cela peut améliorer les performances si la liste des devises est longue ou si les mises à jour des taux de change sont fréquentes.

    3. Affichage du profil utilisateur

    L’affichage d’un profil utilisateur implique l’affichage d’informations statiques telles que le nom, la photo de profil et potentiellement une biographie. L’utilisation de `React.memo` garantit que le composant n’est rendu à nouveau que lorsque les données utilisateur changent réellement, et non à chaque mise à jour du composant parent.

    import React, { memo } from 'react';
    
    const UserProfile = ({ user }) => {
     console.log('UserProfile rendered');
     return (
     

    {user.name}

    Profile

    {user.bio}

    ); }; export default memo(UserProfile);

    Ceci est particulièrement utile si `UserProfile` fait partie d’un tableau de bord ou d’une application plus vaste et fréquemment mis à jour où les données utilisateur elles-mêmes ne changent pas souvent.

    Pièges courants et comment les éviter

    Bien que React.memo soit un outil d’optimisation précieux, il est important d’être conscient des pièges courants et de la façon de les éviter :

    Profilage de votre application

    La meilleure façon de déterminer si React.memo améliore réellement les performances est de profiler votre application. React fournit plusieurs outils de profilage, notamment React DevTools Profiler et l’API React.Profiler.

    React DevTools Profiler vous permet d’enregistrer des traces de performances de votre application et d’identifier les composants qui sont rendus à nouveau fréquemment. L’API React.Profiler vous permet de mesurer le temps de rendu de composants spécifiques par programmation.

    En profilant votre application, vous pouvez identifier les composants qui bénéficieraient le plus de la mémoïsation et vous assurer que React.memo améliore réellement les performances.

    Conclusion

    React.memo est un outil puissant pour optimiser les performances des composants React. En empêchant les nouveaux rendus inutiles, il peut améliorer la vitesse et la réactivité de vos applications, ce qui se traduit par une meilleure expérience utilisateur. Toutefois, il est important d’utiliser React.memo judicieusement et de profiler votre application pour vous assurer qu’elle améliore réellement les performances.

    En comprenant les concepts et les techniques abordés dans cet article de blog, vous pouvez utiliser efficacement React.memo et les techniques connexes pour créer des applications React hautes performances pour un public mondial, en vous assurant que vos applications sont rapides et réactives pour les utilisateurs du monde entier.

    N’oubliez pas de tenir compte des facteurs mondiaux tels que la latence du réseau et les capacités des appareils lors de l’optimisation de vos applications React. En vous concentrant sur les performances et l’accessibilité, vous pouvez créer des applications qui offrent une excellente expérience à tous les utilisateurs, quel que soit leur emplacement ou leur appareil.

    Lectures complémentaires et ressources