整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
終究都要學 React 何不現在學呢? - React 進階 - useCallback - (14)
前言
接下來這一篇算是簡單的一篇,因為我們只會快速認識一下 useCallback,而 useCallback 是什麼呢?就讓我們繼續往下看吧。
useCallback
useCallback 其實與前面 useMemo 非常相似,甚至可以說是 useMemo 的變體也不為過,但…這樣講很模糊,到底 useMemo 跟 useCallback 有何差異呢?
簡單來講這兩個 Hook 都是為了優化 React 渲染效能而誕生的,只是這兩者各自重點皆不同
useMemo- 回傳記憶的值
useCallback- 回傳記憶的函式
記憶是什麼呢?講記憶的感覺好像非常可怕,因此所以你也可以把它理解成「緩存」、「暫存」的概念,所以將上面稍微修正一下就變成以下
useMemo- 回傳記憶、暫存或緩存的值
useCallback- 回傳記憶、暫存或緩存的函式
那麼 useMemo 跟 useCallback 有何差異呢?接著就讓我們來看一下範例。
請注意,以下寫法僅僅只是示範,實務上並不建議你這樣做
而 useMemo 與 useCallback 都是接受一個函式與陣列,並且都是一個表達式
1 | |
但是以結果來講,兩者輸出的都是不同的東西,分別是 2 跟 () => 1 + 1,就如同前面所說的 useMemo 是回傳記憶的值,而 useCallback 是回傳記憶的函式。
那麼這時候這時候問題來了,useCallback 比較常見於哪裡呢?這讓我們先來看一個簡單範例
1 | |
在上方的範例程式碼中,我們使用 setTimeout 模擬 AJAX 的行為,約兩秒後會針對 count 進行加 1 的動作,然而畫面也會有所更新,這邊基本上都是沒有什麼問題的,並且只會執行一次。
但這時候若我們稍微調整一下,拆出一個元件變成以下
1 | |
這時候將範例改成以上之後,有趣的事情發生了,setTimeout 會不停的重複執行,這是為什麼呢?
那麼我們簡單的分析一下上面程式碼的運作流程
App元件被渲染,getData與count也被傳遞給Child元件Child元件被渲染,並且使用useEffect進行監聽,當getData被改變時,就會執行getData函式getData函式被執行,並且進行setTimeout的動作,約兩秒後會執行setCount進行count的更新
到目前為止上方都還沒有什麼問題,但核心重點在於「約兩秒後會執行 setCount 進行 count 的更新」這一段
- 因為
count被更新,因此觸發 re-renderApp元件 App元件因為被重新渲染,因此getData與count也跟著被重新生成並且傳遞給Child元件Child的useEffect發現getData被重新生成,因此會再次執行getData函式
就這樣子發生了無限循環事件。
那麼我們該如何解決呢?這時候就是 useCallback 表演的時候到了,將程式碼調整成以下
1 | |
此時你就可以發現不會一直觸發 setTimeout 了,因為 getData 被包裝成 useCallback 之後,getData 的記憶體位置就不會被重新生成,因此 useEffect 也就不會再次執行 getData 函式。
那麼上方就是一個簡單的 useCallback 說明與範例哩~
後記
本文將會同步更新到我的部落格
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ