重新了解React中的key (Part 1)

MengWei Chen
5 min readOct 13, 2017

--

相信很多人第一次知道在React中有一個key property,是將Data Array用map映射成Component Array時,React跳出警告,要求必須指定key值。

不過key值的用途除了產生Component Array外,還可以處理一些生命週期的問題,接下來會透過幾個範例來帶各位重新了解Key的用途~

這個主題分成兩篇文章
第一篇(Part 1) 主要是透過範例的方式說明Key值到底要給什麼內容才適當
第二篇(Part 2) 是介紹如何利用自訂Key值的方式解決生命週期的問題,若您對Key值已經有基本的了解,歡迎直接跳到第二篇

Key值到底要幹嘛?該放什麼東西進去?

首先請各位先玩一下下方的範例程式,colors陣列存放了各種顏色的名稱,在render時用map映射出Box陣列。為了方便追蹤變化,每一個Box會在constructor時記下初始時的顏色名稱,並帶到background-color當中。另外每一個Box都有綁定滑鼠點擊的事件,觸發後會把自己的顏色名稱從colors陣列中移除。

換句話說就是當點擊Brown時,程式會去把colors內的Brown項目刪除,並且重新render。

值得注意的是,範例中用了兩個radio input來決定key值的內容要用Array的index還是content本身(如”Brown”這個String),藉此就可以觀察key值對於React的行為影響。

請動手玩玩看

稍微玩過一下就可以發現用index當key的情況下,除了點擊最後一個Box以外,都會產生背景跟文字對不起來的問題。使用content當key的情況下,則無這樣的情況。

那究竟是什麼原因使index當key的情況產生非預期的結果呢?

其實我們可以把key這個屬性理解成React用來計算前後差異的實體ID,當我們移除Brown時,移除前跟移除後的Virtual DOM經過Diff計算後,結果就是把key 4的DOM砍掉,並且更新key 2及key 3的DOM。(如下圖)

使用index當key情況

使用content當Key的情況則是一般人所預期得結果,React計算後僅移除Key為 Brown 的DOM(如下圖)

使用content當key情況

對於大部分的情況來說,建議使用資料唯一的值當作Key,以避免非預期的現象發生。若以最常見的User列表為例,則可以使用User的ID。

但無論如何建議都不要使用index+content的組合方式。

接下來我們看一個比較真實的例子,在下方的範例中,我們透過renderContent這個function來產生表格,但由於兩格表格的前半部結構相同,因此當使用者輸入完表格1時,按下切換按鈕後(可以假設是填完表格的下一步),React會重複使用前半部的DOM,導致input的內容沒有被清空。(解決方式也是給定key值)

比較實際一點的例子(表格產生器)
比較實際一點的例子(操作示範)

另一個極端的狀況則是Key重複的問題,假在相同層級內,同時出現了兩個一樣的key,則React v15版以下只會Render出第一次出現的Brown並跳出警告(React v16兩個都會出現)

小結

React在render時若無使用者自訂的key值,則依照同層級中定義的順序當key值。
在React v15以前的版本,若同層級中出現了兩個一樣的key值,則會忽略後來出現的Component。

React在實際修改DOM之前,會比較前一次render跟目前這一次render結果的“差異”,同一個層級中的所有Component

  1. 若出現key值一樣但props不一樣的Component則進行更新
  2. 若比對所有key值後,發現有之前不存在的key值,則新增
  3. 若比對所有key值後,發現有之前存在的key值消失,則刪除

其實Key的使用不只是搭配Array而已,也可以用來解決一些元件更新及生命週期的問題。

請繼續觀看下一篇文章~

--

--