• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
image miniature Canap'Agile
Nouveau podcast Canap’Agile by Ouidou  
2 septembre 2024
Image miniature Le mythe du cast avec TypeScript
Le mythe du cast avec TypeScript
18 septembre 2024
Ressources > Articles techniques > Optimiser les performances dans une application react

Optimiser les performances dans une application react

Écrit par Abdourahmane S.

React a gagné en popularité en tant que l’une des bibliothèques JavaScript les plus prisées pour la création d’interfaces utilisateur, grâce à sa structure basée sur des composants et à son mécanisme de rendu efficace. Cependant, à mesure que votre application React prend de l’ampleur, il devient crucial de se concentrer sur l’optimisation des performances. Dans cet article, nous explorerons les meilleures pratiques pour optimiser les performances des applications React, en présentant des exemples concrets pour vous aider à développer des applications web plus rapides et plus réactives.

L’importance de l’optimisation des performances

  • Expérience Utilisateur Améliorée : Des performances optimisées se traduisent par une expérience utilisateur plus fluide et agréable.
  • Réduction des Temps de Chargement : Des temps de chargement plus courts permettent aux utilisateurs d’accéder rapidement au contenu de l’application.
  • Réactivité Accrue : Une application réactive répond plus rapidement aux actions de l’utilisateur, améliorant ainsi son interactivité.
  • Utilisation Efficace des Ressources : L’optimisation des performances permet une utilisation efficace des ressources du système, ce qui peut réduire les coûts d’infrastructure.
  • Rétention des Utilisateurs : Des performances optimales contribuent à fidéliser les utilisateurs, les incitant à revenir sur l’application.
  • Succès du Projet : Des performances de haut niveau sont souvent associées au succès et à la compétitivité d’un projet dans un marché concurrentiel.

Comment optimiser une application React ?

Utilisation de React.memo() # :

React.memo() est un composant d’ordre supérieur qui optimise le rendu des composants fonctionnels en mémorisant leur état. Il empêche les re-rendus inutiles en vérifiant si les propriétés (props) ont changé par rapport au rendu précédent. Si les props n’ont pas changé, le composant ne se re-rend pas.

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

// Composant pour afficher le nombre de tâches terminées
const CompletedTasks = ({ count }) => {
  console.log('Rendering CompletedTasks');
  return <div>Completed Tasks: {count}</div>;
};

// Mémoriser le composant pour éviter les re-rendus inutiles
const MemoizedCompletedTasks = memo(CompletedTasks);

const TaskApp = () => {
  const [tasks, setTasks] = useState([
    { id: 1, text: 'Review de PR sur Artemis', completed: true },
    { id: 2, text: 'Ecrire les tests unitaires sur Osmie', completed: false },
    { id: 3, text: 'Peer programming', completed: false },
  ]);

  const toggleTaskCompletion = (taskId) => {
    setTasks(tasks.map(task =>
      task.id === taskId ? { ...task, completed: !task.completed } : task
    ));
  };

  const completedCount = tasks.filter(task => task.completed).length;

  return (
    <div>
      <h1>Task List</h1>
      <ul>
        {tasks.map(task => (
          <li key={task.id}>
            <span
              style={{ textDecoration: task.completed ? 'line-through' : 'none' }}
              onClick={() => toggleTaskCompletion(task.id)}
            >
              {task.text}
            </span>
          </li>
        ))}
      </ul>
      <MemoizedCompletedTasks count={completedCount} />
    </div>
  );
};

export default TaskApp;

Utilisation du code splitting # :

Le découpage du code (code splitting) permet de diviser votre application en morceaux plus petits, chargeant uniquement le code nécessaire pour une route ou une fonctionnalité spécifique. Cela réduit le temps de chargement initial et améliore les performances.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

// Utilisation de lazy pour charger les composants de manière asynchrone
const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

const App = () => {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </Suspense>
    </Router>
  );
};

export default App;
  • Lazy : La fonction React.lazy() permet de charger un composant de manière asynchrone. Chaque composant (Home et About) est chargé uniquement lorsque la route correspondante est accédée.
  • Suspense : Le composant Suspense est utilisé pour afficher un fallback (ici, un simple message “Loading…”) pendant que les composants asynchrones sont en cours de chargement.
  • Router : BrowserRouter (nommé ici Router) et Switch de react-router-dom sont utilisés pour gérer les routes de l’application.

PureComponent # :

Si vous utilisez des composants de classe, envisagez d’utiliser PureComponent au lieu de Component. PureComponent effectue une comparaison superficielle des props et de l’état pour déterminer si un composant doit être mis à jour.

import React, { PureComponent } from 'react';

class MyComponent extends PureComponent {
  render() {
    console.log('Rendering MyComponent');
    return <div>Hello, {this.props.name}!</div>;
  }
}

class App extends PureComponent {
  state = {
    name: 'Haouili',
  };

  changeName = () => {
    this.setState({ name: 'Haouili' }); // Même nom, donc pas de changement réel
  };

  render() {
    return (
      <div>
        <button onClick={this.changeName}>Change Name</button>
        <MyComponent name={this.state.name} />
      </div>
    );
  }
}

export default App;
  • Sans PureComponent, MyComponent se re-rend chaque fois que le bouton est cliqué, même si le nom n’a pas changé.
  • Avec PureComponent, MyComponent se re-rend uniquement si name change réellement, améliorant ainsi les performances en évitant les re-rendus inutiles.

Optimisation des rendus coûteux avec useMemo et useCallback # :

Le hook useMemo permet de mémoriser des calculs coûteux, tandis que useCallback mémorise des fonctions pour éviter leur recréation inutile. Utilisez-les lorsque cela est nécessaire pour optimiser les composants critiques en termes de performance.

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

// Composant pour afficher une liste de nombres triés
const SortedList = ({ list }) => {
  const sortedList = useMemo(() => {
    console.log('Tri de la liste');
    return [...list].sort((a, b) => a - b);
  }, 
); return ( <div> <h2>Liste triée</h2> <ul> {sortedList.map((item, index) => ( <li key={index}>{item}</li> ))} </ul> </div> ); }; // Composant principal pour gérer et ajouter des éléments à la liste const App = () => { const
= useState([5, 3, 8, 1]); const [number, setNumber] = useState(''); const addNumber = useCallback(() => { setList((prevList) => [...prevList, parseInt(number)]); setNumber(''); }, [number]); return ( <div> <h1>Liste de nombres </h1> <input type="text" value={number} onChange={(e) => setNumber(e.target.value)} placeholder="Entrez un nombre" /> <button onClick={addNumber}>Ajouter le nombre</button> <SortedList list={list} /> </div> ); }; export default App;
  • Le composant SortedList affiche la liste triée. Grâce à useMemo, la liste est triée uniquement lorsque la liste change, évitant des tris inutiles lors de chaque rendu.
  • Le hook useCallback garantit que la fonction addNumber ne change que lorsque c’est nécessaire, évitant ainsi des ré-rendus inutiles des composants enfants dépendant de cette fonction.

Utilisation de Reselect # :

Reselect est une bibliothèque qui offre une façon élégante de calculer les données dérivées dans un environnement Redux. Il utilise des sélecteurs mémorisés pour extraire des données spécifiques du store Redux et les mémoriser jusqu’à ce que les dépendances changent.

Installation :

npm install redux reselect
import { createSelector } from 'reselect';

// Sélecteur pour récupérer les tâches du store Redux
const getTasks = state => state.tasks;

// Sélecteur pour filtrer les tâches terminées
export const getCompletedTasks = createSelector(
  [getTasks],
  tasks => tasks.filter(task => task.completed)
);

// Sélecteur pour compter le nombre de tâches terminées
export const getCompletedTaskCount = createSelector(
  [getCompletedTasks],
  completedTasks => completedTasks.length
);
  • getCompletedTasks : Ce sélecteur filtre les tâches terminées à partir de la liste complète des tâches.
  • getCompletedTaskCount : Ce sélecteur compte le nombre de tâches terminées en utilisant le résultat du sélecteur précédent.

Ces sélecteurs sont mémorisés, ce qui signifie qu’ils ne seront recalculés que si les données qu’ils utilisent changent.

Utilisation dans un composant Redux :

import React from 'react';
import { connect } from 'react-redux';
import { getCompletedTaskCount } from './selectors';

const TaskCounter = ({ completedTaskCount }) => (
  <div>Nombre de tâches terminées : {completedTaskCount}</div>
);

const mapStateToProps = state => ({
  completedTaskCount: getCompletedTaskCount(state)
});

export default connect(mapStateToProps)(TaskCounter);

Conclusion

Optimiser les performances d’une application est essentiel pour garantir une expérience utilisateur fluide et réactive. Que ce soit en réduisant les temps de chargement initiaux, en minimisant les ré-rendus inutiles, ou en optimisant les calculs coûteux, chaque amélioration apportée contribue à une meilleure expérience globale.

En adoptant des pratiques telles que le chargement différé (lazy loading), la mémorisation des calculs avec des outils comme useMemo et useCallback, ou l’utilisation de bibliothèques spécialisées comme Reselect avec Redux, les développeurs peuvent optimiser leurs applications et garantir des performances optimales.

Cependant, il est également important de garder à l’esprit que l’optimisation des performances ne doit pas compromettre la lisibilité, la maintenabilité ou la qualité du code. Une approche équilibrée qui tient compte à la fois des besoins fonctionnels et des exigences de performances est essentielle pour créer des applications robustes et performantes.

Sources

  • React official website
  • Optimise les performances

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter