Heim >Web-Frontend >js-Tutorial >Grundlegende Techniken zur Optimierung von Reaktionsanwendungen für eine bessere Leistung

Grundlegende Techniken zur Optimierung von Reaktionsanwendungen für eine bessere Leistung

WBOY
WBOYOriginal
2024-08-07 09:35:501145Durchsuche

Essential Techniques to Optimize React Applications for Better Performance

Einführung

Da moderne Webanwendungen immer komplexer werden, wird die Sicherstellung einer optimalen Leistung immer wichtiger. React, eine beliebte JavaScript-Bibliothek zum Erstellen von Benutzeroberflächen, bietet verschiedene Strategien zur Verbesserung der Anwendungsleistung. Unabhängig davon, ob Sie an einem kleinen Projekt oder einer großen Anwendung arbeiten, kann das Verständnis und die Implementierung dieser Optimierungstechniken zu schnelleren Ladezeiten, reibungsloseren Benutzererlebnissen und einer effizienteren Ressourcennutzung führen.

In diesem Beitrag werden wir wesentliche Techniken zur Optimierung von React-Anwendungen untersuchen, von der effizienten Zustandsverwaltung und der Minimierung von erneuten Renderings bis hin zur Nutzung von Code-Splitting und Lazy Loading. Diese Strategien helfen nicht nur bei der Bereitstellung leistungsstarker Anwendungen, sondern auch bei der Aufrechterhaltung der Skalierbarkeit und Reaktionsfähigkeit, wenn Ihre Anwendung wächst. Lassen Sie uns eintauchen und herausfinden, wie Sie das Beste aus Ihren React-Anwendungen herausholen, indem Sie deren Leistung optimieren.

1. React.memo verwenden: Verhindert unnötiges erneutes Rendern

React.memo ist eine Komponente höherer Ordnung, die dazu beitragen kann, unnötige erneute Renderings funktionaler Komponenten zu verhindern. Dabei wird die gerenderte Ausgabe einer Komponente gespeichert und nur dann erneut gerendert, wenn sich ihre Requisiten ändern. Dies kann zu erheblichen Leistungsverbesserungen führen, insbesondere bei Komponenten, die häufig gerendert werden, deren Requisiten sich jedoch nicht oft ändern.

Beispiel

Sehen wir uns ein Beispiel an, in dem wir React.memo verwenden, um unnötige erneute Renderings zu vermeiden:

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;
Erläuterung
  • Wenn Sie auf die Schaltfläche „Anzahl erhöhen“ klicken, wird die CountDisplay-Komponente neu gerendert, da sich ihre Zählstütze ändert.
  • Wenn Sie etwas in das Eingabefeld eingeben, wird die CountDisplay-Komponente nicht erneut gerendert, da ihre Zählstütze unverändert bleibt, auch wenn die übergeordnete App-Komponente erneut gerendert wird.
2. Verwenden Sie useMemo und useCallback Hooks: Merken Sie sich teure Berechnungen

Reacts useMemo- und useCallback-Hooks werden verwendet, um teure Berechnungen und Funktionen zu speichern und so unnötige Neuberechnungen und erneutes Rendern zu verhindern. Diese Hooks können die Leistung in React-Anwendungen erheblich verbessern, insbesondere bei komplexen Berechnungen oder häufig gerenderten Komponenten.

Verwenden Sie Memo

useMemo wird verwendet, um einen Wert zu speichern, sodass er nur dann neu berechnet wird, wenn sich eine seiner Abhängigkeiten ändert.

Beispiel
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;
Erläuterung
  • Durch Klicken auf die Schaltfläche „Anzahl erhöhen“ wird die teure Berechnung ausgelöst, und in der Konsole wird „Berechnung...“ angezeigt.
  • Das Eintippen in das Eingabefeld löst dank useMemo nicht die teure Berechnung aus.
useCallback

useCallback wird verwendet, um eine Funktion zu speichern, sodass sie nur neu erstellt wird, wenn sich eine ihrer Abhängigkeiten ändert.

Beispiel
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;
Erklärung
  • Durch Klicken auf die Schaltfläche „Anzahl erhöhen“ wird die Inkrementierungsfunktion ausgelöst und die Schaltflächenkomponente wird nicht unnötig neu gerendert.
  • Das Eingeben in das Eingabefeld führt dank useCallback nicht dazu, dass die Button-Komponente erneut gerendert wird.
3. Lazy Loading und Code-Splitting: Laden Sie Komponenten dynamisch

Lazy Loading und Code-Splitting sind Techniken, die in React verwendet werden, um die Leistung Ihrer Anwendung zu verbessern, indem Komponenten nur dann geladen werden, wenn sie benötigt werden. Dies kann die anfängliche Ladezeit verkürzen und das allgemeine Benutzererlebnis verbessern.

- Lazy Loading mit React.lazy und Suspense

React bietet eine integrierte Funktion React.lazy, um das verzögerte Laden von Komponenten zu ermöglichen. Es ermöglicht Ihnen, Ihren Code in kleinere Teile aufzuteilen und diese bei Bedarf zu laden.

Beispiel
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;
Erläuterung
1. React.lazy:
  • React.lazy wird verwendet, um die LazyComponent.
  • dynamisch zu importieren
  • Die Importanweisung gibt ein Versprechen zurück, das in die Komponente aufgelöst wird.
2. Spannung:
  • Die Suspense-Komponente wird verwendet, um die Lazy-Loaded-Komponente einzuschließen.
  • Es bietet eine Fallback-Benutzeroberfläche (Laden...), die angezeigt wird, während die Komponente geladen wird.
- Code-Splitting mit React.lazy und React Router

Sie können mit React Router auch Lazy Loading und Code-Splitting verwenden, um Routenkomponenten dynamisch zu laden.

Beispiel
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;
Erläuterung
  • Lazy Load Routenkomponenten:
    React.lazy wird verwendet, um die Home- und About-Komponenten dynamisch zu importieren.

  • Suspense- und React-Router:
    Die Suspense-Komponente umschließt die Routes-Komponente, um eine Fallback-Benutzeroberfläche bereitzustellen, während die Routenkomponenten geladen werden.

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:

    • Rendering-Zeit: Wie lange das Rendern jeder Komponente dauert.
    • Komponentenaktualisierungen: Wie oft Komponenten neu gerendert werden.
    • Interaktionen: Die Auswirkung von Benutzerinteraktionen auf die Leistung

    Letzte Gedanken

    Die Implementierung dieser Optimierungstechniken kann die Leistung von React-Anwendungen erheblich verbessern, was zu schnelleren Ladezeiten, reibungsloseren Interaktionen und einem insgesamt verbesserten Benutzererlebnis führt. Regelmäßige Profilerstellung und Überwachung, kombiniert mit der sorgfältigen Anwendung dieser Techniken, stellen sicher, dass Ihre React-Anwendungen auch bei ihrem Wachstum leistungsfähig und skalierbar bleiben.

    Das obige ist der detaillierte Inhalt vonGrundlegende Techniken zur Optimierung von Reaktionsanwendungen für eine bessere Leistung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

  • Stellungnahme:
    Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn