React 的那些事 — memo

Lee Luciano
Feb 17, 2023

--

這次來聊聊進階一點的話題 memo 的應用,在談論這個話題之前我們先來了解 memo 是什麼?

以下是官方文件翻成中文的解釋:

React memo 是 React 函式組件的高階組件(H.O.C.),用於提高組件的渲染效率。它可以通過記憶組件的渲染結果,避免無效的重新渲染,提高性能。當組件的 props 不變時,它可以返回之前渲染的結果而不是重新渲染。

這裡我就不過多解釋高階組件(H.O.C.)的部分,因為篇幅會很長,重點會放在記憶組件的渲染結果部分,怎麼說呢?下面我用一個母組件嵌套子組件的範例來示範遇到怎樣的問題好了:

此時你的畫面應該會看到如下圖:

當我們按下按鈕時會發現子層的色塊圓圈也跟著重新渲染了,即使他的 props 根本沒發生變化,如下圖:

想要解決以上的問題可以很簡單的利用 React.memo 多包裝一層在 Swatch 之上,React.memo 本身就是一個高階組件(H.O.C.)的型態,你可以簡單理解為多封包一層來改變傳入的 component 屬性就好,有興趣的朋友可以再去尋找 (H.O.C.) 的關鍵字搜尋就好,那麼我們繼續來看套用之後的改變,如下:

我留了兩個色塊讓大家可以比較容易看到差異,那畫面應該會如下圖:

當按下按鈕時會看到有用React.memo處理的component已經不會因為重新渲染按鈕動作而觸發無意義的重複渲染了,如下圖:

這裡稍微提一下新手常常會弄錯的地方,包含我自己在剛學習使用的時候也時常會搞混,要實現這個範例前我們先加一個更換顏色的功能上去,如下:

這樣的使用是沒有問題的,但是當子層的色票組件(component)需要增加更多參數的時候,你會發現原本渲染的機制又壞掉了。如下:

這時你在觀看畫面的 console 會發現 swatch 又壞掉了,即便現在已經使用了 memo 來處理也是一樣,如下圖情況:

這是按下重新渲染按鈕之後的圖,如下:

這是按下換顏色按鈕的圖,如下:

為什麼會發生這種事情呢?這就要回到上一篇 useEffect 的比較機制問題了,簡單來說在使用 React.memo 的同時,它在判斷你的組件是否需要更新是依據你傳入的 props,而傳入的 props 的比較機制又是採用同 useEffect 裏面 dependices array 的機制,也就是說當你傳入的是陣列(array)、物件(object)的話都要另外處理。

怎麼解決這種問題呢?下面提供兩種做法:

第一種,在 memo 裡面用 callback 告訴它從哪裡比較:

第二種,使用 useMemo hook 去處理 params:

那麼你的畫面應該就又回到正常了:

當按下重新渲染,子層不會被觸發了:

按下換顏色才會觸發:

以上就是有關 React.memo 的相關應用知識,我也是看了 Jack Herrington 的教學影片才知道我以前以為的雷區到底是為什麼發生的,之前在用的時候只知道用 memo 的時候一定要搭配 useMemo,不然就有機會會壞掉,但經過他的講解才深入的理解其中的原理,其實並不像想像中那麼玄學。

希望我的分享可以幫助到更多想要更了解 React 框架運作的新手,其實難的不是框架而是 Javascript 本身。

--

--