React 為何不用index當map的key值?
為何不要用Map的index來當作react的key呢?
當我們在寫react時,免不了使用map,用了map如果沒有加key值就會報以下的warning!
而最簡單不報warning的方式就是直接把map出來的key值加上map的index參數。雖然不報warning,但是在效能中卻是一大損傷!因此非常不建議使用index來當key值
主要原因:react會因為key值改變而重新render
react中key的用途:幫助render出的component有效的辨別是否有被刪減、新增、修改!
證明如下:
- 在父層建立一個array並將此陣列map出來並傳到子組件裡面。
- 子組件用PureComponent: 用來辨別組件是否有重新render。
有重新渲染的話會被console出來。
3. 證明方式:利用slice, push, unshift等方法改變陣列內容。
程式碼
A. State部分
父組件 /index.js state = {data: [ { text: "name", value: "Jinwei" }, { text: "gender", value: "male" }, { text: "location", value: "Taiwan" }, { text: "hometown", value: "Nantou" } ]};
B. function部分&測試邏輯
主要有三個function
- removeFirst(): 把原本的data陣列第一個值刪掉
- addIntoFirst(): 把新的值unshift到data陣列的第一項
- addIntoLast(): 把新的值push到data陣列的第一項
removeFirst() { const newData = this.state.data.slice(1); this.setState({ data: newData });}addIntoFirst() { const { data } = this.state; data.unshift(
{text: `index${Math.random()}`,
value: Math.floor(Math.random() * 10)}
); this.setState({ data: data })}
addIntoLast() { const { data } = this.state; data.push(
{text: `index${Math.random()}`, value: Math.floor(Math.random() * 10)}
); this.setState({ data: data })}
C.children組件(ChildList.js)
D. render 部分(index.js)
把畫面呈現出來
主要依據不同的button可以測試不同狀況下react是否做多餘的組件渲染
PS. 測試時可先把其他<h1>部分先註解,可以看得比較清楚!
畫面呈現(當該項component有被render時,就會被console出來)
測試邏輯
如果用index來當作key值的話,則三種function測試結果如下
原本State
state = {data: [
{text:"name",value:"Jinwei"}, {text:"gender",value:"male"}, {text:"location",value:"TW"}, {text:"hometown",value:"NT"}]};
- removeFirst()
Before After
key=0 {text:"name",value:"Jinwei"} {text:"gender",value:"male"}
key=1 {text:"gender",value:"male"} {text:"location",value:"TW"}
key=2 {text:"location",value:"TW"} {text:"hometown",value:"NT"}
key=3 {text:"hometown",value:"NT"}
因此react會覺得四個順序不一樣所以會重新render!
- ↓執行removeFirst()之前的狀況: 畫面第一次render所以都會有console
- ↓執行removeFirst()之後後面三項會被重新render
比較: 不使用index,使用獨特的id
會發現console是空的,組件完全沒有被render!
同理: 可嘗試addIntoFirst()與addIntoLast()試試看(點最下方程式碼範例)
結論
- 用map的index來當key值只要會改變整體的順序,組件就會重新render
- 如果用push加在array後面基本上不會重新render(沒改變順序)
2. 建議如果有能當作key值的資料,就不要用index值,積少成多,整體效能會受影響。但如果沒有其他值能當作key那還是只能用index當key值。
Reference:
- React Lists and Keys
2. HiSkio React教學
React Key範例程式碼: