英文:
Angular 14 NGRX Selector issue
问题
在我的购物篮存储中,您可以看到我有5个物品,其中2个具有ID为4。
在我的reducer中,如果我使用以下代码:
on(getBasket, (state, { id }) => state.filter((photo) => photo.id !== id))
这在某种程度上是有效的,因为购物篮中的物品将被删除,如果购物篮中只有1个特定ID的物品,这是可以接受的。但在这种情况下,上述代码将从购物篮中删除2个条目。所以,为了只删除1个,我需要引入一个选择器来获取ID为4的第一个索引位置(我不关心删除哪一个)。
所以我尝试编写以下代码:
export const basketPosition = createSelector(
(state: Array<Photo>, { id }: any) => state.indexOf(id)
)
其中state将是购物篮,id将是4。然而,整个语句被标记为红色,我看不出这个语句有什么问题。它一直显示以下错误信息:
源具有1个元素,但目标需要3个。
英文:
So in my basket store you can see that I have 5 items 2 have an id 0f 4.
in my reducer, if I use:
on(getBasket, (state, { id }) => state.filter((photo) => photo.id !== id)
this works as far as it goes in that the item in the basket will be removed which is fine if I only have 1 item of a particular id in the basket otherwise in this scenario the above will remove 2 entries from the basket. So to only remove 1 I need to introduce a selector to obtain the first index position for id 4 in this case (I dont care which one is removed).
So I have attempted to write:
export const basketPosition = createSelector(
((state: Array<Photo>, { id }: any) => { return state.indexOf(id) })
)
Where state will be basket, and the id would be 4. However The whole statement red lines and I cannot see what is wrong with that statement. it just keeps stating:
> Source has 1 element(s) but target requires 3.
答案1
得分: 0
你如何提供state
和id
给选择器basketPosition
?createSelector()
需要一些状态来从中选择内容,根据你的示例,可以像下面这样:
export interface Things {
basket: Basket[];
selectedPhotos: Photos[];
}
// 从状态中选择特定数据
export const selectBasket = (state: Things) => state.basket;
export const selectPhotos = (state: Things) => state.selectedPhotos;
// 从`selectPhotos`数据数组中返回第一个元素
export const selectOnePhoto = createSelector(selectPhotos, (photos: Photos[]) => photos[0]);
// 从`selectBasket`数据数组中返回所有元素
export const selectAllItems = createSelector(selectBasket, (basket) => basket);
如果需要向选择器传递参数,可以像下面这样提供一个(或多个):
export const selectItemById = (id: string) => createSelector(
selectBasket,
(basket) => {
// ... 这里添加一些逻辑...
return basket.find(b => b.id === id);
}
)
// 从组件中调用它
item$!: Observable<Item | undefined>;
ngOnInit(): void {
this.item$ = this.store.select(selectBasket('someId'));
}
英文:
How are you providing state
and id
to the selector basketPosition
...? createSelector()
needs some State in order to select something from it, giving your example, it could be like the following:
export interface Things {
basket: Basket[];
selectedPhotos: Photos[];
}
// selecting a specific data from the state
export const selectBasket = (state: Things) => state.basket;
export const selectPhotos = (state: Things) => state.selectedPhotos;
//from `selectPhotos` data array, return the first element
export const selectOnePhoto = createSelector(selectPhotos, (photos: Photos[]) => photos[0]);
//from the selectBasket data array, return all elements
export const selectAllItems = createSelector(selectBasket, (basket) => basket);
If you require to pass an argument to a selector
, you can provide one (or many) like the following:
export const selectItemById = (id: string) = createSelector(
selectBasket,
(basket) => {
// ... some logic here...
return basket.find(b => b.id === id);
}
)
// calling it from a component
item$!: Observable<Item | undefined>;
ngOnInit(): void {
this.item$ = this.store.select(selectBasket('someId'));
}
答案2
得分: 0
我已经弄清楚了如何在购物篮中删除多个相同项目中的单个项目。所以我创建了一个操作:
export const removeFromBasket = createAction('[Basket Component] removeFromBasket', props<{ id: number }>());
然后我创建了一个减速器:
on(removeFromBasket, (state, { id }) => {
const basketArray = [...state];
basketArray.splice(state.findIndex(tt => tt.id === id), 1);
return basketArray;
}),
然后在我的组件中调用减速器:
RemoveFromBasket(photo: Photo) {
this.basketStore.dispatch(removeFromBasket({ id: photo.id }));
}
英文:
Ok, Took me a while but I have figured out how to remove a single item from my basket when I have multiple of the same item.
So I create an action:
export const removeFromBasket = createAction('[Basket Component] removeFromBasket', props<{ id: number }>());
then I create a reducer:
on(removeFromBasket, (state, { id }) => {
const basketArray = [...state];
basketArray.splice(state.findIndex(tt => tt.id === id), 1);
return basketArray;
}
),
then in my component I call the reducer :
RemoveFromBasket(photo: Photo) {
this.basketStore.dispatch(removeFromBasket({ id :photo.id }));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论