提高網站效能是增強使用者體驗和確保可靠、響應靈敏的介面的關鍵一步。如果您正在開發包含一些資源密集型元件的 React 或 Next.js 項目,那麼很自然會擔心它們對效能的影響。這就是 React 中的記憶化的用武之地——它有助於加快這些「昂貴」組件的速度,從而為用戶帶來更流暢的體驗。
在本文中,我將介紹記憶化並介紹可以最佳化應用程式效能的 React hooks,例如 useMemo()、useCallback() 和 React.memo 高階元件 (HOC)。讓我們開始吧!
記憶化是一種透過快取計算任務(例如函數呼叫)的結果來加速程式的技術,這樣,如果再次提供相同的輸入,則傳回快取的結果而不是重新計算它。
useMemo 是一個鉤子,可以在重新渲染或更新元件之間快取或記憶函數的結果。
因此,透過使用此鉤子,您可以快取元件中函數的結果,並且在下次重新渲染時,如果函數的輸入未更改,您的元件將使用快取結果。
useMemo 是一個掛鉤,它將未最佳化的函數作為回調和依賴項列表。然後 React 決定何時在初始渲染期間或後續重新渲染時呼叫此函數。
初始渲染:在初始渲染期間,React 會呼叫 useMemo 函數來計算並儲存您提供的回調函數的結果。
重新渲染:重新渲染時,React 呼叫 useMemo 來檢查依賴項是否已更改。如果依賴項沒有更改,React 會重複使用上次渲染期間儲存的快取值。但是,如果依賴項發生變化,useMemo 會再次呼叫回調函數來重新計算更新後的值並將其儲存在快取中。
範例:
import React, { useMemo } from 'react'; const MyComponent = ({ number }) => { const squaredNumber = useMemo(() => number * number, [number]); return <div>Squared Number: {squaredNumber}</div>; };
squaredNumber 僅當數字改變時才計算。 useMemo 會快取此計算,因此不會在每次渲染時進行不必要的重新計算。
useCallback 是一個鉤子,用於快取或記憶元件重新渲染或更新之間的函數定義。
透過使用這個鉤子,你可以在重新渲染時儲存函數的定義,因此只要函數的依賴項沒有改變,React就會重複使用這個快取的版本。
useCallback 是一個掛鉤,它接受一個函數(作為回調)和一個依賴項列表。然後,React 決定何時返回(而不是調用)此函數 - 無論是在初始渲染期間還是在後續重新渲染期間。
初始渲染:在初始渲染期間,React 呼叫 useCallback 來儲存您作為回調傳遞的函數。
重新渲染:重新渲染時,React 呼叫 useCallback 來檢查依賴項是否已更改。如果依賴項沒有更改,React 會重複使用上次渲染期間儲存的快取函數。如果依賴項發生更改,useCallback 將儲存並傳回更新後的函數。
範例:
import React, { useMemo } from 'react'; const MyComponent = ({ number }) => { const squaredNumber = useMemo(() => number * number, [number]); return <div>Squared Number: {squaredNumber}</div>; };
如你所知,當你有父元件和子元件時,對父元件的 state 或 props 的任何更新都會導致其所有子元件重新渲染。在小型專案中,這可能不是問題,但在更大、更複雜的應用程式中,子元件不必要的重新渲染可能會影響效能。為了解決這個問題,React 提供了 memo() 函數。
memo(或 React.memo)函數可讓您包裝元件以防止其在父級更新時重新渲染。包裝的元件只有在其自身的 props 或 state 改變時才會重新渲染。
當你第一次在元件上呼叫 memo() 時,React 會渲染並快取該元件。在後續渲染中,只要元件的 props 和狀態沒有改變,React 就會使用這個快取的版本。請記住,memo() 僅避免重新渲染未更改的 props 和狀態 - 一旦它們發生更改,memo() 就會相應地重新渲染並更新快取的元件。
要在元件中實作 memo,只需使用 memo() 或 React.memo() 包裝您想要防止不必要的重新渲染的元件:
import React, { useState, useCallback } from 'react'; const MyComponent = () => { const [count, setCount] = useState(0); const [multiplier, setMultiplier] = useState(2); // Memoize the callback with `count` as a dependency const calculate = useCallback(() => { console.log("Calculating:", count * multiplier); }, [count]); return ( <div> <p>Count: {count}</p> <p>Multiplier: {multiplier}</p> <button onClick={() => setCount(count + 1)}>Increment Count</button> <button onClick={() => setMultiplier(multiplier + 1)}>Increment Multiplier</button> <button onClick={calculate}>Calculate</button> </div> ); }; export default MyComponent;
注意:
如果將物件作為 prop 傳遞給包裝在 memo() 中的元件,則即使該物件沒有更改,該元件仍將在每次更新時重新渲染。發生這種情況是因為 React 使用 Object.is 來比較先前和目前的 props。雖然 Object.is(3, 3) 傳回 true,但 Object.is({}, {}) 傳回 false,因為兩個不同的物件參考永遠不會被視為相等。
為了避免這種情況,您可以使用 useMemo 來快取物件並在渲染之間保持相同的參考:
import React from 'react'; const MyComponent = ({ data }) => { return <div>{data.value}</div>; }; export default React.memo(MyComponent);
在此範例中,useMemo 確保資料物件具有相同的引用,從而防止 MyComponent 不必要的重新渲染。
謝謝您閱讀我的文章!如果您想了解有關 Next.js、React、JavaScript 等的更多信息,請隨時關注我的網站:saeed-niyabati.ir。如有任何問題,請隨時與我們聯絡。下次見!
以上是透過記憶化提高 React 應用程式的效能:探索 useMemo、useCallback 和 React.memo的詳細內容。更多資訊請關注PHP中文網其他相關文章!