嗨,我是Hogan
目前在經營自己的自媒體 hogan.tech
主要分享一些有關於程式碼、軟體和科技業經驗分享
有興趣的讀者可以進一步關注我,進而獲得更多資訊唷!
未來文章一併更新於此網站 Hogan.B Lab
並且包含多語系 繁體中文、英文、日文、簡體中文
觀看分類:React 白話文運動、其他系列
如果想要快速查找其他文章請點選目錄
成立 hogan.tech 的初衷是
希望每個正在這條路上探索的人,
都可以透過 Hogan.tech 嘗試進入程式領域。
前一篇會介紹useContext 的使用方法
這一篇會介紹新的 hook - useMemo
因為 useEffect,有使用到相依陣列
所以先來用陣列舉例,在 JavaScript 中,看起來相同的陣列,其實本質上是不同的
可以試著執行看看,就會發現這兩個陣列不相同
理由是陣列、物件、函式,都是依據是否是相同實體(instance)來去做判斷
if([1,3] != [1,3]){
console.log("this is the not same instance")
}
又拿以下的例子來說,這邊可以發現是相同的,因為他們是相同的實體
const array = [1,2,3];
if(array === array){
console.log("this is the same instance")
}
因此我們在使用 useEffect 時,相依陣列裡面的值是物件、陣列、函式,無論如何都會因為是不同的實體,而再去觸發一次並且執行 useEffect 裡面的函式
這邊我也舉了另一個例子,會造成嚴重效能問題
如果用以下舉例,我這邊做了一個點擊按鈕就會往上加一的元件
不過我又另外做了一個函式,叫做 expensiveCalculation 他只做一件事
就是跑十億次的迴圈,並且每次跑完就往上加一
如果讀者執行下面這段程式碼就會發現,元件會被強制重複渲染,造成跑很慢
import { useEffect } from "react";
import { useMemo } from "react";
import { useState } from "react";
export default function Increment() {
const [count, setCount] = useState(0);
const calculation = useEffect(() => expensiveCalculation(count), [count]);
const increment = () => {
setCount((c) => c + 1);
};
return (
<div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
在講解 useMemo 用法之前,需要講一下所謂的記憶化(Memorization),useMemo 會呼叫傳遞給她的引數函數來計算並且儲存結果。
所以以上述的例子來說,如果 useEffect 改成 useMemo 則就會記憶 expenciveCalculation 的結果,只有在相依陣列變動時才會重新計算函式的輸出結果。
這邊我強烈推薦想要深入了解 Memorization 的讀者可以參考這篇文章
這邊也附上我覺得很好的例子
如果嘗試執行下面的程式,就會發現元件渲染變快非常多
理由也是因為在執行第一次渲染的同時,也記住了 expensiveCalculation
只有當count有做修改時,再去做函式的計算
import { useEffect } from "react";
import { useMemo } from "react";
import { useState } from "react";
export default function Increment() {
const [count, setCount] = useState(0);
const calculation = useMemo(() => expensiveCalculation(count), [count]);
const increment = () => {
setCount((c) => c + 1);
};
return (
<div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
這一篇在講解 useMemo 的用法,同時也複習了一下 useEffect 的相依陣列
在哪些情況會導致重複渲染,因此用 useMemo 可以提高效能
如果有任何建議與疑問也歡迎留言!
如果喜歡此系列文章,請不吝於按下喜歡及分享,讓更多人看到唷~