【React】警惕加入動畫導致因key產生的渲染錯誤

前言

  • 我這次寫個多選框,多選框其實挺好寫的,但是如果要加入動畫效果,那就有點不太好搞了。做這個動畫,還犯了個key的錯誤,導致渲染錯誤,讓我想記錄下來。

多選框原理

  • 先說下我的多選框原理,爲了後面讀者可以瞭解這個key的錯誤到底怎麼發生的。
  • 正常不帶動畫的多選框,就是有個狀態去記錄傳來data的索引,然後有個狀態根據索引記錄要渲染的data,這樣當選中一個data,那麼這個data會記錄到索引,然後索引改變後就改變state,再根據state改變渲染結果。
  • 而選中刪除則是獲取了選中的元素索引,匹配到索引表,索引表進行修改,索引表改變後改變記錄的state,最後改變整個渲染結果。
  • 沒動畫的寫起來沒毛病,一下子就搞定了,但是有動畫就不一樣了。
  • 有動畫的思路是當選中一個data,那麼最終改變state使得渲染的元素在出現時進行下類名變換。
  • 而刪除,則是獲取選中元素,進行類名變化,使得其消失,setTimeout後改變索引表和state。
  • 這個坑就在刪除上。

key造成的渲染錯誤效果

  • 正常來說,我們渲染個列表,很容易就想到拿index當key,我一開始也是這麼想的,事實上不加動畫也沒問題。但是加動畫了就會產生個奇怪結果。
  • 我選中一個元素進行刪除,比如1、2、3、4號元素,我刪除3號,當我點擊刪除後,3號因爲類名變化消失,setTimeout後,進行修改索引表和state(與頁面元素相關狀態)表,事實上這個索引表和state表的計算結果完全正確,都是我想要保留的,但是,渲染結果卻是隻有1號元素和2號元素,4號元素不見了!
  • 因爲發現改變state表進行刷新後,所有狀態都是完全正確的,所以我才發現問題出在key上。

key造成渲染錯誤的原因

  • 因爲我用index做key,所以1234號元素的key是1.2.3.4(索引從0開始,爲了方便理解寫1234)。
  • 然後進行刪除3號元素,這時,3號元素會切換類名改變,由於類名改變並且自身會調一個刪除自己的方法,導致此時的渲染結果頁上,3號元素動畫完成後消失(包括dom)。此時父組件並未重新渲染,因爲這個類名切換並刪除自己是3號元素自身的狀態行爲。
  • 這時,會進行setTimeout,setTimeout裏進行setState設置父組件索引表以及state。索引表就爲1,2,4。而setState會產生組件刷新,此時重新渲染頁面元素,本來的3號元素已經沒了,4號變成了3號的位置,且用了3號的索引,react在reconciller就會發現,上一次索引表是1,2,3,4,這一次是1,2,4,那麼只要刪掉3號元素就好了。結果它就把你4號元素當成3號元素給刪掉了。

解決方案

  • 正確設置key,我這個例子裏,用index+item的方式也不靠譜,因爲如果item重名就不行,但是索引表卻是不會重名的,所以我就利用索引表當key設置。
  • 多選框線上遊玩地址

總結

  • 如果簡單邏輯key設index沒啥毛病,複雜邏輯需要注意key的設置,特別是做動畫之類,如果有錯誤渲染且狀態全部正常情況,優先考慮是不是key引發的錯誤。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章