提问人:Nayrb 提问时间:10/15/2023 更新时间:10/16/2023 访问量:31
将对象添加到 NgRx reducer 中 state 中包含的另一个对象中的子对象数组中
Add object to child object array in another object contained in state within an NgRx reducer
问:
我无法找出将新对象添加到包含在一段状态中的数组的正确语法。该数组是另一个对象的一部分,也是我的状态的一部分。
在我的情况下,我有包含对象数组 Card[] 的 Deck 对象。您可以在我的状态对象 currentDeck 中看到这一点。
我发现任何在化简器外部操作currentDeck的尝试都会导致错误“can't define array index property past the end of an array of an un-writable length”。这让我意识到,经过一些研究,我需要在减速器中正确地做到这一点。
我有一个 NgRx 效果,它调度一个成功操作 addCardCurrentDeckSuccess,该操作将一张新卡添加到牌组中。这不仅需要更改卡牌阵列,还需要更改我假设的套牌。我调度的操作传入了需要添加到当前甲板对象 Card[] 的卡片中。
我在 Deck 对象中有一个 addCard 方法,我认为解决方案中需要它。
我的代码和数据结构如下。我已经删除了大多数不相关的变量和其他 reducer 操作。
目前,我正在寻找一种不需要安装“浸入式”模块的解决方案。我已经做了一些标准化数据集的阅读,但我不确定我如何在这里做到这一点。
任何帮助将不胜感激。
我的状态和 Reducer
export interface MyState {
decks: [],
currentDeck : Deck;
}
export const initialState: MyState = {
currentDeck: undefined,
}
const reducer = createReducer(
initialState,
on(saveCurrentDeckActions.saveCurrentDeckSuccess, (state, { currentDeck }) => ({
...state,
currentDeck
})),
on(addDeckActions.addDeckSuccess, (state, { deck }) => ({
...state,
decks: [...state.decks, deck]
})),
on(addCardToCurrentDeckActions.addCardCurrentDeckSuccess, (state, { card }) => ({
/* Can't seem to nail down the syntax here
currentDeck.AddCard(card) */
}))
);
export const MyFeature = createFeature({
name: 'MyFeatureSelectors',
reducer
})
// Deck
import {Card} from "./card.model"
export class Deck {
deckId : string = "";
name : string = "";
cards : Card[] = [];
constructor() {
this.deckId = "";
this.name = "";
this.cards = [];
}
public addCards(cards: Card[]) {
this.cards.push.apply(this.cards, cards);
}
public getCards() : Card[] {
return this.cards;
}
public addCard(card : Card) {
this.cards.push(card);
}
}
//Card
export class Card {
name: string
id: string
constructor(json? : any) {
this.name = json?.name;
this.id = json?.id;
}
}
答:
你不能调用,因为它会改变数组,从而改变状态,这违反了 ngrx 的基本规则之一——状态应该是不可变的。Array.push
您需要通过 reducer 以不可变的方式执行所有这些状态更改。
也不要存储为 a,因为这会复制数组中存在的相同状态,这违反了单一事实来源原则 - 请改用索引。currentDeck
Deck
deck
export interface MyState {
decks: Deck[],
currentDeckIndex : number;
}
...
on(addCardToCurrentDeckActions.addCardCurrentDeckSuccess, (state, { card }) => {
// add the card to a a copy of the relevant deck
const updatedDeck = [...state.decks[currentDeckIndex], card];
// replace decks with an array that has the updated deck inserted
return {
... state,
decks: state.decks.map((deck, index) => index === currentDeckIndex ? updatedDeck : deck)
};
})
评论