iT邦幫忙

2022 iThome 鐵人賽

DAY 19
3
Software Development

React框架白話文運動系列 第 19

React白話文運動19-React Hook-useMemo

  • 分享至 

  • xImage
  •  

前言

嗨,我是Hogan
目前在經營自己的自媒體 hogan.tech
主要分享一些有關於程式碼、軟體和科技業經驗分享
有興趣的讀者可以進一步關注我,進而獲得更多資訊唷!

未來文章一併更新於此網站 Hogan.B Lab
並且包含多語系 繁體中文英文日文簡體中文
觀看分類:React 白話文運動其他系列

如果想要快速查找其他文章請點選目錄

成立 hogan.tech 的初衷是
希望每個正在這條路上探索的人,
都可以透過 Hogan.tech 嘗試進入程式領域。


前一篇會介紹useContext 的使用方法

  1. 加入Context
  2. 透過Context Consumer讀取資料
  3. 透過 useContext 讀取資料

這一篇會介紹新的 hook - useMemo

  1. 複習 useEffect 的相依陣列
  2. useMemo用法

複習 useEffect

相依陣列

因為 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 裡面的函式

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用法

Memoization 記憶化

在講解 useMemo 用法之前,需要講一下所謂的記憶化(Memorization),useMemo 會呼叫傳遞給她的引數函數來計算並且儲存結果。

所以以上述的例子來說,如果 useEffect 改成 useMemo 則就會記憶 expenciveCalculation 的結果,只有在相依陣列變動時才會重新計算函式的輸出結果。

這邊我強烈推薦想要深入了解 Memorization 的讀者可以參考這篇文章

這邊也附上我覺得很好的例子

image

useMemo 語法

如果嘗試執行下面的程式,就會發現元件渲染變快非常多

理由也是因為在執行第一次渲染的同時,也記住了 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 可以提高效能

如果有任何建議與疑問也歡迎留言!

如果喜歡此系列文章,請不吝於按下喜歡及分享,讓更多人看到唷~


上一篇
React白話文運動18-React Hook-useContext 02
下一篇
React白話文運動20-React Hook-useCallback
系列文
React框架白話文運動30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言