介紹

我寫 React 程式碼已經 3 年多了。然而,我最初沒有關注的一件事是優化 React 效能。大多數時候,技術債會不斷積累,優化性能變得充滿挑戰。

從一開始就專注於優化是相當困難的,但您可以不時地安排優化以避免巨大的技術債。

我們將研究 React 的一些優化技術。這可以在您編寫程式碼時實現。問題在於選擇這種方法而不是另一種方法。

那麼,讓我們開始吧。

  1. 優化大列表

渲染清單很常見,因為 React 中有元件。渲染大型清單具有挑戰性,因為它可能會導致渲染緩慢和記憶體使用。虛擬化是處理此類問題的最佳方法。它僅渲染可見列表,其他專案將在需要時渲染。

React Window 和 React Virtualized 是虛擬化清單中流行的函式庫。它們僅渲染視窗中可見的專案,從而顯著減少在任何給定時間渲染的 DOM 節點的數量。

這是一個 React Window 的範例:

    import { FixedSizeList as List } from 'react-window';

    const MyList = ({ items }) => (
      <List
        height={500} // Height of the container
        itemCount={items.length} // Total number of items
        itemSize={35} // Height of each item
        width={300} // Width of the container
      >
        {({ index, style }) => (
          <div style={style}>
            {items[index]}
          </div>
        )}
      </List>
    );

  1. useMemo

useMemo 是一個 React hook,用於記住計算結果。因此,除非依賴關係發生變化,否則它不允許對計算進行多次處理。在函數或計算成本昂貴且不應在每次渲染上重新執行的情況下,這對於最佳化效能很有用。

useMemo 的語法是:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

如您所見,useMemo 有兩個參數:

  • 一個傳回值以便可以記憶的函數。

  • 一組依賴項,用於確定何時應重新計算儲存的值。

這是 useMemo 的範例:

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

    const ExpensiveComponent = ({ a, b }) => {
      const computeExpensiveValue = (a, b) => {
        console.log('Computing expensive value...');
        return a + b;
      };

      const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

      return (
        <div>
          <p>Computed Value: {memoizedValue}</p>
        </div>
      );
    };

    const ParentComponent = () => {
      const [a, setA] = useState(1);
      const [b, setB] = useState(2);
      const [count, setCount] = useState(0);

      return (
        <div>
          <ExpensiveComponent a={a} b={b} />
          <button onClick={() => setCount(count + 1)}>Increment Count</button>
        </div>
      );
    };

  1. 程式碼分割

在傳統設定中,應用程式的所有元件都捆綁到一個檔案中。程式碼分割是一種最佳化技術,用於將應用程式分解為更小的區塊。當您載入較小的元件時,它會減少應用程式的載入時間,並避免使用其他不必要的元件。

這是程式碼分割的範例:

    import React, { useState } from 'react';

    function App() {
      const [component, setComponent] = useState(null);

      const loadComponent = async () => {
        const { default: LoadedComponent } = await import('./MyComponent');
        setComponent(<LoadedComponent />);
      };

      return (
        <div>
          <h1>Code Splitting Example</h1>
          <button onClick={loadComponent}>Load Component</button>
          {component}
        </div>
      );
    }

    export default App;

  1. React.Lazy

React.Lazy 是優化載入元件的重要方法。它使您能夠延遲載入元件。這意味著僅在需要時才載入該元件。使用它,您可以將應用程式拆分為更小的元件並按需載入。

React.lazy()用於動態導入元件。當需要該元件時,它會非同步加載,在此之前,可以顯示後備 UI(如加載微調器)。

這是延遲載入的範例:

    import React, { Suspense } from 'react';

    const LazyComponent = React.lazy(() => import('./MyComponent'));

    const App = () => {
      return (
        <div>
          <h1>My App</h1>
          <Suspense fallback={<div>Loading...</div>}>
            <LazyComponent />
          </Suspense>
        </div>
      );
    };

    export default App;

  1. Throttle & Debounce

它不僅是 React 特有的,也是呼叫函數時的通用程式設計。節流是一種定義函數執行頻率的技術。當函數被限制時,無論事件被觸發多少次,它只允許在指定的時間間隔內執行一次。例如,為按鈕點擊新增限制,以便按鈕不會被過於頻繁地呼叫。

Throttle範例:

    import React, { useState } from 'react';

    function ThrottledButton() {
      const [count, setCount] = useState(0);

      const throttle = (func, delay) => {
        let lastCall = 0;
        return () => {
          const now = new Date().getTime();
          if (now - lastCall >= delay) {
            lastCall = now;
            func();
          }
        };
      };

      const incrementCount = () => {
        setCount((prevCount) => prevCount + 1);
      };

      const throttledIncrement = throttle(incrementCount, 2000);

      return (
        <div>
          <h1>Count: {count}</h1>
          <button onClick={throttledIncrement}>Click Me</button>
        </div>
      );
    }

    export default ThrottledButton;

去抖動用於確保函數在呼叫函數後一定時間後應被執行。當事件重複發生時,去抖函數只會在事件停止觸發指定的延遲時間後執行。例如,當使用者輸入搜尋輸入並提供建議時,我們會在呼叫函數之前等待幾毫秒,以便使用者完成輸入。

Debounce範例:

    import React, { useState } from 'react';

    function debounce(func, delay) {
      let timeoutId;
      return function (...args) {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
          func(...args);
        }, delay);
      };
    }

    const DebouncedSearch = () => {
      const [query, setQuery] = useState('');

      const handleSearch = (event) => {
        setQuery(event.target.value);
        console.log('Searching for:', event.target.value);
        // Here you would typically trigger an API call or filter a list based on the query
      };

      const debouncedSearch = debounce(handleSearch, 500);

      return (
        <div>
          <h1>Search</h1>
          <input
            type="text"
            placeholder="Type to search..."
            onChange={debouncedSearch}
          />
          <p>Search Query: {query}</p>
        </div>
      );
    };

    export default DebouncedSearch;

原文出處:https://dev.to/surajondev/optimizing-react-applications-for-maximum-performance-5epm

按讚的人:

共有 0 則留言