Memoized selector with computation in @ngrx/store
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
My normalized ngrx store looks like this:
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;
}
It's a pretty basic setup where a cart can contain several items.
My selector needs to return an array with all the carts with arrays containing their items, but also compute if items are in danger of dropping out of their respective cart:
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 => {
// computations, should not run if cart's items have not changed
// needs to be memoized
const computed = isCartOverfilled(i, c, items);
return {
id: i.id,
mightFallOut: computed//computed value needs to be output
}
})
}
});
});
Every time an item updates, isCartOverfilled will run for each item in the store. But, isCartOverfilled is potentially expensive and depends only on the items inside a cart. When an item updates, e.g. gets added to a cart, isCartOverfilled should execute ONLY for the items inside, i.e. memoized by cart id.
How do I achieve this?
I have tried selecting items from a single cart:
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
}
})
}
});
This selector would not excessively compute, but I need all the carts, and I'm not sure if it's doable with a selector.
typescript ngrx ngrx-store reselect ngrx-entity
add a comment |
My normalized ngrx store looks like this:
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;
}
It's a pretty basic setup where a cart can contain several items.
My selector needs to return an array with all the carts with arrays containing their items, but also compute if items are in danger of dropping out of their respective cart:
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 => {
// computations, should not run if cart's items have not changed
// needs to be memoized
const computed = isCartOverfilled(i, c, items);
return {
id: i.id,
mightFallOut: computed//computed value needs to be output
}
})
}
});
});
Every time an item updates, isCartOverfilled will run for each item in the store. But, isCartOverfilled is potentially expensive and depends only on the items inside a cart. When an item updates, e.g. gets added to a cart, isCartOverfilled should execute ONLY for the items inside, i.e. memoized by cart id.
How do I achieve this?
I have tried selecting items from a single cart:
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
}
})
}
});
This selector would not excessively compute, but I need all the carts, and I'm not sure if it's doable with a selector.
typescript ngrx ngrx-store reselect ngrx-entity
add a comment |
My normalized ngrx store looks like this:
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;
}
It's a pretty basic setup where a cart can contain several items.
My selector needs to return an array with all the carts with arrays containing their items, but also compute if items are in danger of dropping out of their respective cart:
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 => {
// computations, should not run if cart's items have not changed
// needs to be memoized
const computed = isCartOverfilled(i, c, items);
return {
id: i.id,
mightFallOut: computed//computed value needs to be output
}
})
}
});
});
Every time an item updates, isCartOverfilled will run for each item in the store. But, isCartOverfilled is potentially expensive and depends only on the items inside a cart. When an item updates, e.g. gets added to a cart, isCartOverfilled should execute ONLY for the items inside, i.e. memoized by cart id.
How do I achieve this?
I have tried selecting items from a single cart:
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
}
})
}
});
This selector would not excessively compute, but I need all the carts, and I'm not sure if it's doable with a selector.
typescript ngrx ngrx-store reselect ngrx-entity
My normalized ngrx store looks like this:
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;
}
It's a pretty basic setup where a cart can contain several items.
My selector needs to return an array with all the carts with arrays containing their items, but also compute if items are in danger of dropping out of their respective cart:
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 => {
// computations, should not run if cart's items have not changed
// needs to be memoized
const computed = isCartOverfilled(i, c, items);
return {
id: i.id,
mightFallOut: computed//computed value needs to be output
}
})
}
});
});
Every time an item updates, isCartOverfilled will run for each item in the store. But, isCartOverfilled is potentially expensive and depends only on the items inside a cart. When an item updates, e.g. gets added to a cart, isCartOverfilled should execute ONLY for the items inside, i.e. memoized by cart id.
How do I achieve this?
I have tried selecting items from a single cart:
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
}
})
}
});
This selector would not excessively compute, but I need all the carts, and I'm not sure if it's doable with a selector.
typescript ngrx ngrx-store reselect ngrx-entity
typescript ngrx ngrx-store reselect ngrx-entity
edited Jan 3 at 16:53
Ante Novokmet
asked Jan 3 at 14:16


Ante NovokmetAnte Novokmet
1436
1436
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
As the state is already changed the selector will recalculate.
But you can achieve using keeping another state for cart and when you dispatch addCart Item action you can update the cart with single item instead of using selector.
export interface State {
carts: EntityState<Cart>;
cartOverFilled: SomeState or part of Cart State <---
items: EntityState<Item>;
}
or
export interface State {
carts: EntityState<CartState>;
items: EntityState<Item>;
}
export interface CartState {
cart: Cart;
overFilled: any
}
export interface Cart {
id: number;
maxVolume: number;
}
- Add one more state with values to check overfilled;
- Create an effect for ofType 'Add to cart '
- Create another action to recalculate the with existing state of overfilled with incoming item.
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54024066%2fmemoized-selector-with-computation-in-ngrx-store%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As the state is already changed the selector will recalculate.
But you can achieve using keeping another state for cart and when you dispatch addCart Item action you can update the cart with single item instead of using selector.
export interface State {
carts: EntityState<Cart>;
cartOverFilled: SomeState or part of Cart State <---
items: EntityState<Item>;
}
or
export interface State {
carts: EntityState<CartState>;
items: EntityState<Item>;
}
export interface CartState {
cart: Cart;
overFilled: any
}
export interface Cart {
id: number;
maxVolume: number;
}
- Add one more state with values to check overfilled;
- Create an effect for ofType 'Add to cart '
- Create another action to recalculate the with existing state of overfilled with incoming item.
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
add a comment |
As the state is already changed the selector will recalculate.
But you can achieve using keeping another state for cart and when you dispatch addCart Item action you can update the cart with single item instead of using selector.
export interface State {
carts: EntityState<Cart>;
cartOverFilled: SomeState or part of Cart State <---
items: EntityState<Item>;
}
or
export interface State {
carts: EntityState<CartState>;
items: EntityState<Item>;
}
export interface CartState {
cart: Cart;
overFilled: any
}
export interface Cart {
id: number;
maxVolume: number;
}
- Add one more state with values to check overfilled;
- Create an effect for ofType 'Add to cart '
- Create another action to recalculate the with existing state of overfilled with incoming item.
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
add a comment |
As the state is already changed the selector will recalculate.
But you can achieve using keeping another state for cart and when you dispatch addCart Item action you can update the cart with single item instead of using selector.
export interface State {
carts: EntityState<Cart>;
cartOverFilled: SomeState or part of Cart State <---
items: EntityState<Item>;
}
or
export interface State {
carts: EntityState<CartState>;
items: EntityState<Item>;
}
export interface CartState {
cart: Cart;
overFilled: any
}
export interface Cart {
id: number;
maxVolume: number;
}
- Add one more state with values to check overfilled;
- Create an effect for ofType 'Add to cart '
- Create another action to recalculate the with existing state of overfilled with incoming item.
As the state is already changed the selector will recalculate.
But you can achieve using keeping another state for cart and when you dispatch addCart Item action you can update the cart with single item instead of using selector.
export interface State {
carts: EntityState<Cart>;
cartOverFilled: SomeState or part of Cart State <---
items: EntityState<Item>;
}
or
export interface State {
carts: EntityState<CartState>;
items: EntityState<Item>;
}
export interface CartState {
cart: Cart;
overFilled: any
}
export interface Cart {
id: number;
maxVolume: number;
}
- Add one more state with values to check overfilled;
- Create an effect for ofType 'Add to cart '
- Create another action to recalculate the with existing state of overfilled with incoming item.
edited Jan 4 at 15:00
answered Jan 3 at 14:52


rijinrijin
1,059515
1,059515
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
add a comment |
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
I am aware of the first point. As for the second, are you suggesting I move computation to the reducer and actually store the computed state to store? Is there a way to create such a selector that when it recalculates, only recomputes items from a single cart?
– Ante Novokmet
Jan 3 at 16:43
Dispatch another action
– rijin
Jan 3 at 16:45
Dispatch another action
– rijin
Jan 3 at 16:45
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54024066%2fmemoized-selector-with-computation-in-ngrx-store%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown