Here is the structure of my normalized ngrx store:
export interface State {
carts: EntityState<Cart>;
items: EntityState<Item>;
}
export interface Cart {
id: number;
maxVolume: number;
}
export interface Item {
id: number;
cartId: number;
volume: number;
}
In this setup, a cart can hold multiple items. My goal is to have a selector that returns an array of all carts with arrays containing their items and also evaluates if any items are at risk of falling out of their respective carts:
export const select: MemoizedSelector<object, any> = createSelector(
selectAllCarts, selectAllItems,
(allCarts: Cart[], allItems: Item[]) => {
return allCarts.map(c => {
const items = allItems.filter(i => i.cartId == i.id);
return {
id: c.id,
items: items.map(i => {
// Perform computations only when necessary
// Make sure these computations are memoized
const computed = isCartOverfilled(i, c, items);
return {
id: i.id,
mightFallOut: computed
}
})
}
});
});
Whenever an item is updated, the isCartOverfilled function needs to be executed for each related item in the store. However, this function can be computationally expensive and should only run for the items within a specific cart. How can I achieve this?
I attempted to select items from a single cart using the following approach:
export const selectCart = (cartId: number) => createSelector(
selectItemsByCartId(cartId), selectCartById(cartId),
(items: Item[], cart: Cart) => {
return {
id: cart.id,
items: items.map(i => {
const computed = isCartOverfilled(i, cart, items);
return {
id: i.id,
mightFallOut: computed
}
})
}
});
Although this selector avoids excessive computation, it only focuses on one cart. I still need to include all carts in the output. I am uncertain if achieving this with a selector is feasible.