Maison >interface Web >js tutoriel >Techniques essentielles pour optimiser les applications React pour de meilleures performances

Techniques essentielles pour optimiser les applications React pour de meilleures performances

WBOY
WBOYoriginal
2024-08-07 09:35:501142parcourir

Essential Techniques to Optimize React Applications for Better Performance

Introduction

À mesure que les applications Web modernes gagnent en complexité, garantir des performances optimales devient de plus en plus critique. React, une bibliothèque JavaScript populaire pour la création d'interfaces utilisateur, propose diverses stratégies pour améliorer les performances des applications. Que vous travailliez sur un petit projet ou une application à grande échelle, la compréhension et la mise en œuvre de ces techniques d'optimisation peuvent conduire à des temps de chargement plus rapides, à des expériences utilisateur plus fluides et à une utilisation plus efficace des ressources.

Dans cet article, nous explorerons les techniques essentielles pour optimiser les applications React, depuis la gestion efficace de l'état et la minimisation des nouveaux rendus jusqu'à l'exploitation du fractionnement de code et du chargement paresseux. Ces stratégies aideront non seulement à fournir des applications hautes performances, mais également à maintenir l'évolutivité et la réactivité à mesure que votre application se développe. Plongeons-nous et découvrons comment tirer le meilleur parti de vos applications React en optimisant leurs performances.

1. Utilisez React.memo : évite les nouveaux rendus inutiles

React.memo est un composant d'ordre supérieur qui peut aider à éviter les nouveaux rendus inutiles des composants fonctionnels. Il fonctionne en mémorisant la sortie rendue d'un composant et en la restituant uniquement si ses accessoires changent. Cela peut conduire à des améliorations significatives des performances, en particulier pour les composants qui sont fréquemment rendus mais dont les accessoires ne changent pas souvent.

Exemple

Voyons un exemple dans lequel nous utilisons React.memo pour éviter les nouveaux rendus inutiles :

import React, { useState } from 'react';

// A functional component that displays a count
const CountDisplay = React.memo(({ count }) => {
  console.log('CountDisplay rendered');
  return <div>Count: {count}</div>;
});

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

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <CountDisplay count={count} />

      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
};

export default App;
Explication
  • Lorsque vous cliquez sur le bouton « Incrémenter le nombre », le composant CountDisplay sera restitué car son accessoire de comptage change.
  • Lorsque vous tapez dans le champ de saisie, le composant CountDisplay ne sera pas restitué car son accessoire de comptage reste inchangé, même si le composant App parent est restitué.
2. Utilisez useMemo et useCallback Hooks : mémorisez des calculs coûteux

Les hooks useMemo et useCallback de React sont utilisés pour mémoriser des calculs et des fonctions coûteux, évitant ainsi les recalculs et les rendus inutiles. Ces hooks peuvent améliorer considérablement les performances des applications React, en particulier lorsqu'il s'agit de calculs complexes ou de composants fréquemment rendus.

utiliserMémo

useMemo est utilisé pour mémoriser une valeur, elle n'est donc recalculée que lorsqu'une de ses dépendances change.

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

const ExpensiveCalculationComponent = ({ num }) => {
  const expensiveCalculation = (n) => {
    console.log('Calculating...');
    return n * 2; // Simulate an expensive calculation
  };

  const result = useMemo(() => expensiveCalculation(num), [num]);

  return <div>Result: {result}</div>;
};

const App = () => {
  const [num, setNum] = useState(1);
  const [text, setText] = useState('');

  return (
    <div>
      <button onClick={() => setNum(num + 1)}>Increment Number</button>
      <ExpensiveCalculationComponent num={num} />

      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
};

export default App;
Explication
  • Cliquer sur le bouton "Incrémenter le nombre" déclenche le calcul coûteux et vous verrez "Calcul en cours..." enregistré dans la console.
  • Taper dans le champ de saisie ne déclenche pas le calcul coûteux, grâce à useMemo.
utiliserCallback

useCallback est utilisé pour mémoriser une fonction, elle n'est donc recréée que lorsqu'une de ses dépendances change.

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

const Button = React.memo(({ handleClick, label }) => {
  console.log(`Rendering button - ${label}`);
  return <button onClick={handleClick}>{label}</button>;
});

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

  const increment = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []);

  return (
    <div>
      <Button handleClick={increment} label="Increment Count" />
      <div>Count: {count}</div>

      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
};

export default App;
Explication
  • Cliquer sur le bouton « Incrémenter le nombre » déclenche la fonction d'incrémentation et le composant Button n'est pas restitué inutilement.
  • La saisie dans le champ de saisie ne provoque pas le nouveau rendu du composant Button, grâce à useCallback.
3. Chargement paresseux et fractionnement de code : charger dynamiquement les composants

Le chargement paresseux et le fractionnement de code sont des techniques utilisées dans React pour améliorer les performances de votre application en chargeant les composants uniquement lorsqu'ils sont nécessaires. Cela peut réduire le temps de chargement initial et améliorer l'expérience utilisateur globale.

- Chargement paresseux avec React.lazy et Suspense

React fournit une fonction intégrée React.lazy pour permettre le chargement paresseux des composants. Il vous permet de diviser votre code en morceaux plus petits et de les charger à la demande.

Exemple
import React, { Suspense } from 'react';

// Lazy load the component
const MyLazyComponent = React.lazy(() => import('./MayLazyComponent'));

const App = () => {
  return (
    <div>
      <h1>Welcome to My App</h1>

      {/* Suspense component wraps the lazy loaded component */}
      <Suspense fallback={<div>Loading...</div>}>
        <MyLazyComponent />
      </Suspense>
    </div>
  );
};

export default App;
Explication
1. Réagissez.lazy :
  • React.lazy est utilisé pour importer dynamiquement le LazyComponent.
  • L'instruction d'importation renvoie une promesse qui résout le composant.
2. Suspense :
  • Le composant Suspense est utilisé pour envelopper le composant chargé paresseux.
  • Il fournit une interface utilisateur de secours (Chargement...) à afficher pendant le chargement du composant.
- Séparation de code avec React.lazy et React Router

Vous pouvez également utiliser le chargement différé et le fractionnement de code avec React Router pour charger dynamiquement les composants de la route.

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

// Lazy load the components
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

const App = () => {
  return (
    <Router>
      <div>
        <h1>My App with React Router</h1>

        <Suspense fallback={<div>Loading...</div>}>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
          </Routes>
        </Suspense>
      </div>
    </Router>
  );
};

export default App;
Explication
  • Composants d'itinéraire de chargement paresseux :
    React.lazy est utilisé pour importer dynamiquement les composants Accueil et À propos.

  • Routeur Suspense et React :
    Le composant Suspense encapsule le composant Routes pour fournir une interface utilisateur de secours pendant le chargement des composants d'itinéraire.

4. Virtualize Long Lists: Renders only the visible items

Virtualizing long lists in React using libraries like react-window or react-virtualized can significantly improve performance by rendering only the visible items. This technique is essential for handling large datasets efficiently and ensuring a smooth user experience.

Example
import React from 'react';
import { List } from 'react-virtualized';

const rowRenderer = ({ index, key, style }) => (
  <div key={key} style={style}>
    Row {index}
  </div>
);

const App = () => {
  return (
    <List
      width={300}
      height={400}
      rowCount={1000}
      rowHeight={35}
      rowRenderer={rowRenderer}
    />
  );
};

export default App;
5. Debounce & Throttle Events: Limits the frequency of expensive operations

Debouncing and throttling are essential techniques to optimize performance in React applications by controlling the frequency of expensive operations. Debouncing is ideal for events like key presses, while throttling is more suited for continuous events like scrolling or resizing. Using utility libraries like Lodash can simplify the implementation of these techniques.

- Debounce

Debouncing ensures that a function is only executed once after a specified delay has passed since the last time it was invoked. This is particularly useful for events that trigger frequently, such as key presses in a search input field.

Example using Lodash
import React, { useState, useCallback } from 'react';
import debounce from 'lodash/debounce';

const App = () => {
  const [value, setValue] = useState('');

  const handleInputChange = (event) => {
    setValue(event.target.value);
    debouncedSearch(event.target.value);
  };

  const search = (query) => {
    console.log('Searching for:', query);
    // Perform the search operation
  };

  const debouncedSearch = useCallback(debounce(search, 300), []);

  return (
    <div>
      <input type="text" value={value} onChange={handleInputChange} />
    </div>
  );
};

export default App;
- Throttle

Throttling ensures that a function is executed at most once in a specified interval of time. This is useful for events like scrolling or resizing where you want to limit the rate at which the event handler executes.

Example using Lodash
import React, { useEffect } from 'react';
import throttle from 'lodash/throttle';

const App = () => {
  useEffect(() => {
    const handleScroll = throttle(() => {
      console.log('Scrolling...');
      // Perform scroll operation
    }, 200);

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    <div style={{ height: '2000px' }}>
      Scroll down to see the effect
    </div>
  );
};

export default App;
6. Optimize Images and Assets: Reduces the load time

Optimizing images and assets involves compressing files, using modern formats, serving responsive images, and implementing lazy loading. By following these techniques, you can significantly reduce load times and improve the performance of your React application.

Use the loading attribute for images to enable native lazy loading or use a React library like react-lazyload.

Example
import React from 'react';
import lazyImage from './lazy-image.webp';

const LazyImage = () => {
  return (
    <div>
      <img
        src={lazyImage}
        alt="Lazy Loaded"
        loading="lazy" // Native lazy loading
        style={{ width: '100%', maxWidth: '300px' }}
      />
    </div>
  );
};

export default LazyImage;
7. Avoid Inline Functions and Object Literals:

Avoiding inline functions and object literals is important for optimizing performance in React applications. By using useCallback to memoize functions and defining objects outside of the render method, you can minimize unnecessary re-renders and improve the efficiency of your components.

Example
// 1. Inline Function

// Problematic Code:
 <button onClick={() => setCount(count + 1)}>Increment</button>

// Optimized Code:
  // Use useCallback to memoize the function
  const handleClick = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []);

 <button onClick={handleClick}>Increment</button>

// 2. Inline Object Literals

// Problematic Code:
    <div style={{ padding: '20px', backgroundColor: '#f0f0f0' }}>
      <p>Age: {age}</p>
    </div>

// Optimized Code:
    const styles = {
         container: {
             padding: '20px',
             backgroundColor: '#f0f0f0',
        },
    };

    <div style={styles.container}>
      <p>Age: {age}</p>
    </div>
8. Key Attribute in Lists: React identify which items have changed

When rendering lists in React, using the key attribute is crucial for optimal rendering and performance. It helps React identify which items have changed, been added, or removed, allowing for efficient updates to the user interface.

Example without key attribute

In this example, the key attribute is missing from the list items. React will not be able to efficiently track changes in the list, which could lead to performance issues and incorrect rendering.

    <ul>
      {items.map((item) => (
        <li>{item}</li>
      ))}
    </ul>
Example with key attribute as index

In the optimized code, the key attribute is added to each

  • element. The key value should be a unique identifier for each item. In this case, the index of the item is used as the key. However, it's recommended to use a unique identifier (e.g., item.id) if available, as using indices can cause issues if the list items are reordered or changed.

       <ul>
          {items.map((item, index) => (
            <li key={index}>{item}</li>
          ))}
        </ul>
    
    Example with Unique Identifiers:

    In this example, each list item has a unique id which is used as the key. This approach provides a more reliable way to track items and handle list changes, especially when items are dynamically added, removed, or reordered.

        <ul>
          {items.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
    
    9. Use Production Build:

    Always use the production build for your React app to benefit from optimizations like minification and dead code elimination.

    Build Command: npm run build
    10. Profile and Monitor Performance:

    Profiling and monitoring performance are crucial for ensuring that your React application runs smoothly and efficiently. This involves identifying and addressing performance bottlenecks, ensuring that your application is responsive and performs well under various conditions.

    - Use React Developer Tools

    React Developer Tools is a browser extension that provides powerful tools for profiling and monitoring your React application. It allows you to inspect component hierarchies, analyze component renders, and measure performance.

    - Analyze Performance Metrics

    Use the performance metrics provided by React Developer Tools to identify slow components and unnecessary re-renders. Look for:

    • Temps de rendu : combien de temps prend chaque composant pour être rendu.
    • Mises à jour des composants : à quelle fréquence les composants sont restitués.
    • Interactions : l'impact des interactions des utilisateurs sur les performances

    Pensées finales

    La mise en œuvre de ces techniques d'optimisation peut considérablement améliorer les performances des applications React, conduisant à des temps de chargement plus rapides, des interactions plus fluides et une expérience utilisateur globalement améliorée. Un profilage et une surveillance réguliers, combinés à une application minutieuse de ces techniques, garantissent que vos applications React restent performantes et évolutives à mesure de leur croissance.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

  • Déclaration:
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn