昨天做 task 的時候,遇到了一個問題。
TypeError: can't define property "x": "obj" is not extensible
而我的代碼是
public txTiles: Array<TransactionFilterTile>;
constructor(private _store: Store<AppStore>){
_store.select(str => str.transactionState.tiles).subscribe(tiles => {
this.txTiles = tiles;// tiles是一個對象數組
this.txTiles.forEach( (x) => {
x.currentStyle = { 'border-color': `${x.htmlColor}` };// 給currentStyle屬性再賦值
});
}
}
究其原因,項目中使用了 ngrx/store,它是 RXJS 的一種超牛叉的狀態管理,由 Redux 支持。Redux 可以確保 state 變化的可預測性,主要的約束有:
- state 以單一對象存儲在 store 對象中;
- state 只讀
- 使用純函數 reducer 執行 state 更新
所以,服務器端的響應數據是隻讀的,且只能通過 dispatch(action)來觸發更新,所以在 ts 文件裏面不能隨意給 tile 的屬性重新賦值,可我又不想通過 dispatch 改變底層數據,那麼該怎麼辦呢? 我們可以克隆獲取的數據。修改後的代碼爲:
_store.select(str => str.transactionState.tiles).subscribe(tiles => {
this.txTiles = [];// 構建空數組
if (tiles && tiles.length) {
tiles.forEach(x => {
self.txTiles.push(new TransactionFilterTile(x));
});
}
this.txTiles.forEach( (x) => {
x.currentStyle = { 'border-color': `${x.htmlColor}` };// 給currentStyle屬性再賦值
});
}
也就是構建空數組,然後把獲取到的數據放到空數組中,這樣既可以不更改底層數據,又可以在本組件中對從服務器獲取到的數據進行修改。