文章目錄
- useCallback的優缺點
- 優點
- 缺點
- JavaScript 的內聯優化
- 使用場景
用了兩年多的react,今天抽空寫點小內容
useCallback的優缺點
緩存了每次渲染時候 inline callback的實例
優點
關鍵點:利用memoize減少無效的re-render,通常配合shouldComponentUpdate 或者 React.memo 起到減少不必要渲染的目的
- 性能優化:useCallback可以幫助避免每次渲染的時候創建新的函數實例。這對于將函數作為props傳遞給子組件的時候特別有用,因為子組件可以使用React.memo 來進行淺比較,從而避免不必要的重新渲染
- 依賴性控制: useCallback 接受一個依賴數組作為第二個參數,使得你可以明確指定哪些變量的變化應該導致函數重新創建。這有助于精確控制依賴,避免不必要的重新計算。
缺點
- 過度使用可能導致性能問題:useCallback可能會阻止某些優化(如內聯)
- 增加復雜性:在簡單組件中,使用useCallback 可能會顯得過于繁瑣,因此優先考慮組件的復雜性和性能需求,權衡是否使用useCallback
- 可能引入bug:如果依賴數組設置不當,導致函數被錯誤緩存
JavaScript 的內聯優化
- 內聯優化:內聯指的是 將函數調用代碼直接插入到調用處,而不是通過函數調用方式執行,這樣可以減少函數調用的開銷,提高性能。當使用useCallback 包裹一個函數時候,React 可能無法在一些情況進行內聯,因為useCallback返回的是同一個函數實例,而不是新的函數
const memoizedCallback = useCallback(() => {// function body
}, [/* dependencies */]);// 內聯優化可能受到影響
<SomeComponent onClick={memoizedCallback} />
- 對象緩存:內聯也與對象的創建和緩存有關。如果一個函數內部創建了對象,并且該函數被useCallback緩存,那么對象可能被緩存在在閉包中,導致無法及時被垃圾回收。這可能會在長時間運行的應用中引起內存泄露問題
const memoizedCallback = useCallback(() => {const obj = { key: 'value' };// 使用 obj
}, [/* dependencies */]);// obj 可能無法及時被垃圾回收
為了確保在不再需要時能夠及時釋放對象并觸發垃圾回收,你可以采取以下步驟:
import { useCallback, useEffect, useRef } from 'react';const MyComponent = () => {const memoizedObject = useRef(null);memoizedObject.current = useCallback(() => {const obj = { key: 'value' };// 使用 objreturn obj;}, [/* dependencies */]);// ...// 如果 memoizedObject 不再被使用,設置為 null 或者清除引用useEffect(() => {return () => {// 清除對 memoizedObject 的引用// 這樣,在組件卸載或 memoizedObject 不再使用時,可以及時觸發垃圾回收memoizedObject.current = null;};}, []);// ...
};
在這個例子中,我們使用 useEffect 來監聽組件的生命周期,并在組件即將卸載時執行清理操作。通過將 memoizedObject.current 設置為 null 或清除引用,我們告訴垃圾回收器這個對象不再被需要。這有助于確保在組件卸載或不再需要時能夠及時釋放對象并觸發垃圾回收。
請注意,這里使用了 memoizedObject.current,因為在 React Hooks 中,我們經常使用 useRef 來保存可變的值,并確保在組件重新渲染時保持其穩定性。如果你使用 useRef 來保存 memoizedObject,你可以在 useEffect 中設置 memoizedObject.current 為 null 或清除引用。
使用場景
- 函數被 useEffect 內部所引用了,但為了避免頻繁的useEffect的頻繁調用,可以選擇包一下;
- 需要保存一個函數閉包結果,如配合 debounce、throttle使用;
- useCallback包裹的函數,但某個依賴項變化時,引用這個函數的所有 useEffect 都得重新執行一下;
最后分享一個外鏈:Day383:說下 React 的 useEffect、useCallback、useMemo