useCallback 是一個(gè)允許你在多次渲染中緩存函數(shù)的 React Hook。即只有在依賴項(xiàng)發(fā)生變化時(shí)才會(huì)重新生成該函數(shù)。
即在以下情況下才有意義(官網(wǎng)):
- 將其作為 props 傳遞給包裝在 [
memo] 中的組件。如果 props 未更改,則希望跳過重新渲染。緩存允許組件僅在依賴項(xiàng)更改時(shí)重新渲染。- 傳遞的函數(shù)可能作為某些 Hook 的依賴。比如,另一個(gè)包裹在
useCallback中的函數(shù)依賴于它,或者依賴于 [useEffect] 中的函數(shù)。
哦~~ 緩存作用~ ~,let me做個(gè)測(cè)試看看是否真的緩存了!!
看個(gè)常見的場景
在列表上(父組件)提供了個(gè)批量導(dǎo)入數(shù)據(jù)的按鈕A(即圖中"批量新增房源"),點(diǎn)擊A后會(huì)彈出彈窗(子組件BatchInsertHouse),彈窗上可進(jìn)行上傳和取消操作,點(diǎn)擊這兩個(gè)按鈕會(huì)觸發(fā)父組件注入的回調(diào)。

image.png
// 列表(父組件)
...
//彈窗顯隱
const [batchAddHousesDialog, setBatchAddHousesDialog] = useState<boolean>(false);
//打個(gè)時(shí)間戳
const timestamp = new Date().getTime();
console.log('父render timestamp:',timestamp)
//關(guān)閉彈窗回調(diào)
const closeUploadHousesExcel = () => {
console.log('函數(shù)timestamp:',timestamp)
setBatchAddHousesDialog(false);
};
...
return (
...
{/* 彈窗子組件 */}
<BatchInsertHouse
visible={batchAddHousesDialog}
closeFn={closeUploadHousesExcel}
...
></BatchInsertHouse>
...
)
如上代碼,父組件向子組件(BatchInsertHouse)注入了closeUploadHousesExcel事件,當(dāng)點(diǎn)擊了彈窗的"取消"就會(huì)執(zhí)行closeUploadHousesExcel函數(shù);
- 此時(shí)點(diǎn)擊按鈕A后看控制臺(tái):
- 點(diǎn)擊取消:
新增兩條 - 再次點(diǎn)擊按鈕A:
新增一條 - 再次取消:
新增兩條, 看紅色部分
可以看到隨著彈窗的顯示隱藏父組件會(huì)跟著render,并且我們?cè)赾loseUploadHousesExcel內(nèi)打印的時(shí)間戳也在不停變化,說明每次都生成了一個(gè)新的函數(shù);
添加useCallback
讓我們加上useCallback再試一次:
//其他代碼不變
const closeUploadHousesExcel = useCallback(() => {
console.log('函數(shù)timestamp:',timestamp)
setBatchAddHousesDialog(false);
},[]);
- 此時(shí)點(diǎn)擊按鈕A:
- 點(diǎn)擊取消:
綠色新增 - 當(dāng)我們?cè)俅吸c(diǎn)擊按鈕A:
綠色新增 - 再次取消:
綠色新增,看紅色部分
因?yàn)槲覀兊暮瘮?shù)closeUploadHousesExcel已經(jīng)被緩存了,所以每次拿到的timestamp都是最開始緩存的那一個(gè)number!?。。?!也就不會(huì)變化。
結(jié)論
誠不欺我,確實(shí)是緩存住啦~







