Lala Code

Lala 的前端大補帖,歡迎一起鑽研前端技術😊

0%

【DAY 19】useCallback 函式記憶體

cover

[情境劇場]

解師傅:嘿!想跟你調整一下菜盤數量,今天會請六月天樂團來表演
小當家:這個昨天不是講過了!?更新後的菜色我已經在準備了
解師傅:恩~對…只是不一樣的是..他們會包遊覽車過來,本來一桌的菜要變三桌了…
小當家:我懷疑他們是來蹭飯的吧!!!


認識 useCallback

基本上 useCallback 的目的就跟 useMemo 一樣,都是為了儲存記憶體的 Memorized Hook,只差在 useMemo 是回傳值,而 useCallback 是回傳 callback function,在 dependencies 沒有改變的情況下,把某個 function 保存下來,減少不必要的重新渲染





useCallback 使用方法

  • 從 react 中載入 useCallback 方法
  • useCallback 帶入參數,第一個參數為函式,第二個參數為 dependencies 陣列



1. 從 react 中載入 useCallback 方法

1
import { useCallback } from "react";



2. useCallback 帶入參數

1
const memoizedValue = useCallback (() => { doSomething(a) }, [a]);

第一個參數為函式,函式回傳不必要重新渲染的程式

第二個參數為 dependencies 陣列,useCallback 會依 dependencies 陣列去做比對差異,如果 dependencies 有變動,才會重新渲染,並回傳 callback function
如沒有 dependencies,則放空陣列,每次 render 時都會計算新的值。





useCallback 使用情境

  • 依賴本地 stateprops 來創建函數,需要使用到緩存函數的地方
  • useEffect 的 dependencies 為 function


Object、 Array 因為是 by reference ,所以使用 useMemo 包裝,而 useCallback 也是一樣意思, useCallback 是把function儲存起來再來做 function 的比對, function 也是 by reference,雖然是一樣的內容,但經過比對會是不一樣的 function

1
2
3
4
5
6
7
const functionOne = function() {
return 1;
};
const functionTwo = function() {
return 1;
};
console.log(functionOne === functionTwo); // false


[範例]

App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { useState } from "react";
import Child from "./components/Child";

function App() {
const [count, setCount] = useState(0);
const [value, setValue] = useState("");

const childCount = () => {
return [count + 1, count + 2, count + 3];
};

return (
<div>
<h1>現在號碼:{count}</h1>

<input
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
placeholder="無關緊要的 input"
/>

<Child childCount={childCount} />

<button
onClick={() => {
setCount((state) => state + 1);
}}
>
下一位
</button>
</div>
);
}

export default App;

components/Child.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { useEffect, useState } from "react";

const Child = (props) => {
const { childCount } = props;

const [count, setCount] = useState([]);

useEffect(() => {
console.log("render Child");
setCount(childCount());
}, [childCount]);

return <h1>排隊號碼:{count.join(", ")}</h1>;
};

export default Child;

簡單說明情境:

  • 畫面有一個計數器,點擊按鈕 count 會 + 1
  • childCount 函式,會回傳 count 下三個數字的陣列
  • 導入顯示排隊號碼的 Child 組件,傳入 props (childCount 函式)
  • 一個無關緊要的 input,用來測試 Child 組件是否跟著 re-render

現在我們點擊下一位,也會很正常的渲染 Child 組件






但在輸入 input 時,發生了什麼事你應該也猜到了!!






useCallback

沒錯!明明跟組件無關,但輸入 input 時也 render 了 Child 組件



這時我們可以用 useCallback 來解決~

1
2
3
const childCount = useCallback(() => {
return [count + 1, count + 2, count + 3];
}, [count]);


現在輸入 input 也不會影響到 Child 組件囉!用 useCallback 包住以確保 count 變動才會重新渲染


結語

useCallback 跟 useMemo 用法其實大同小異,
其實 useCallback(fn, deps) 就同等於 useMemo(() => fn, deps)

他們有相同的特性,當然同樣的也不要過度使用,最好是用在執行速度很慢、變動性不大的函式,以減少重新渲染的目的


本文為 IT 鐵人賽系列文 你 React 了嗎? 30 天解鎖 React 技能




Hey!想學習更多前端知識嗎?

最近 Lala 開了前端課程 👉【實地掌握RWD - 12小時新手實戰班】👈
無論您是 0 基礎新手,又或是想學 RWD 的初學者,
我們將帶你從零開始,深入了解並掌握 RWD 響應式網頁設計的核心技術,快來一起看看吧 😊



🚀線上課程分享

線上課程可以加速學習的時間,省去了不少看文件的時間XD,以下是我推薦的一些課程
想學習更多關於前後端的線上課程,可以參考看看。

Hahow

Hahow 有各式各樣類型的課程,而且是無限次數觀看,對學生或上班族而言,不用擔心被時間綁住



六角學院

如果你是初學者,非常推薦六角學院哦!
剛開始轉職也是上了六角的課,非常的淺顯易懂,最重要的是,隨時還有線上的助教幫你解決問題!


Udemy

Udemy 裡的課程非常的多,品質普遍不錯,且價格都滿實惠的,CP值很高!
也是很多工程師推薦的線上課程網站。
❤️