我寫 React 程式碼已經 3 年多了。然而,我最初沒有關注的一件事是優化 React 效能。大多數時候,技術債會不斷積累,優化性能變得充滿挑戰。
從一開始就專注於優化是相當困難的,但您可以不時地安排優化以避免巨大的技術債。
我們將研究 React 的一些優化技術。這可以在您編寫程式碼時實現。問題在於選擇這種方法而不是另一種方法。
那麼,讓我們開始吧。
渲染清單很常見,因為 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>
);
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>
);
};
在傳統設定中,應用程式的所有元件都捆綁到一個檔案中。程式碼分割是一種最佳化技術,用於將應用程式分解為更小的區塊。當您載入較小的元件時,它會減少應用程式的載入時間,並避免使用其他不必要的元件。
這是程式碼分割的範例:
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;
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;
它不僅是 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