項目地址:kolodny/immutability-helperjavascript
輪子做用:以最低的成本對抗淺比較。java
適用場景:state的修改。git
若是使用redux管理數據流,就必然會遇到state的修改。state修改有個特性,redux會進行一次新舊state的淺比較,若是有變更纔會觸發從新渲染。一個大的項目state的數據結構必然會很複雜,若是有一個很裏層的數據被修改,這時就很頭疼。github
若是把state深拷貝一次會十分浪費資源,因此咱們不會這麼幹。淺拷貝一樣行不通,由於淺拷貝以後的操做會改變舊的state值,這既不規範,也不會觸發渲染。redux
假如咱們有以下一個state:antd
state = {
info: {
name: "tom",
age: 12
},
score: {
exam1: [99, 98, 89],
exam2: [78, 85]
}
}
複製代碼
進行一次淺拷貝copyState = state
,此時的copyState
與state
其實保存了相同的值,他們指向內存中的同一片區域。若是如今我進行一番操做:數據結構
state.score.exam2.push(90);
複製代碼
對於copyState
與state
而言,他們其實沒有任何變化,依舊指向同一片內存區域,只是這片區域內保存的數據有了變化,因此此時二者仍然相等。性能
因此淺複製天然也就沒法對抗淺比較,並且還可能出現意想不到的反作用(修改state致使copyState也變了)。學習
一個比較原始地方法就是把state照抄一遍,並進行所需的修改:spa
newState = {
info: state.info,
score: {
exam1: state.score.exam1,
exam2: [
state.score.exam2[0],
state.score.exam2[1],
90
],
},
}
複製代碼
這就是最大程度上利用原有數據,在不深拷貝的狀況下定向修改數據,而且返回一個新對象的操做。
可是上面的操做明顯就很笨拙,在ES6引入了...
操做符之後,這個操做就能夠獲得簡化:
newState = {
...state,
score: {
...state.score,
exam2: [
...state.score.exam2,
90,
],
},
}
複製代碼
可是能夠想象,在數據層級比較深的時候就會寫得很複雜,上面的...state.score.exam2
已是不短的一串代碼了。
面對着這種困境,immutability-helper就是一個與使用...
操做邏輯相同,可是書寫要簡便不少的輪子。這個輪子有必定的學習成本。上面的例子使用immutability-helper實現的具體操做以下:
import update from 'immutability-helper';
newState = update(state, {
score: {
exam2: {
$push: [90]
}
}
})
複製代碼
不難看出,用了immutability-helper之後少寫了不少沒必要要的代碼,immutability-helper實現的功能還不單單只是這些,有興趣能夠自行研究一下源碼。它也是一個被antd推薦使用的輪子。
總而言之,十分推薦在React中使用immutability-helper來進行state的更新,兼具性能與優雅。