Reputation: 1382
I am using Angular 5, ngrx/store. I have an effect:
@Effect()
updateAfterChanges$ = this.actions$.pipe(
ofType(ActionTypes.ChangesInItems),
withLatestFrom(
this.store.select(fromReducers.getItemsList)
),
switchMap(([action, itemsList]: [ActionType, Items[]]) => {
return [new UpdateItems()]
})
)
getItemsList
looks like this:
export const getItemsList= createSelector(
fromAnotherReducer.getAllItems,
getCurerntItemdId,
(allItems, itemId) => collectItems(allItems, allItems[itemId].subItems)
);
This selector called on absolutely another page - page1
. Where i don't have items at all. Items are loaded from the server when i open model window on page2
.
So on the page1
i am getting an error Cannot read property 'subItems' of undefined
. Why this selector even called not after ofType(ActionTypes.ChangesInItems)
? I must add a check in selector:
Object.keys(allItems).length !== 0 ?
collectItems(allItems, allItems[itemId].subItems) : []
Why is this happening? I don't want to add checks in every selector that uses dynamically loaded data. I expect that effect will be called only in response to ofType(ActionTypes.ChangesInItems)
Upvotes: 4
Views: 1602
Reputation: 225
This is an expected behaviour, it's how withLatestFrom works, so it will start listening to the given observable immediately, but it will only emit the value when source get emitted!
This example will explain what’s happening:
So the console.log inside test()
will shown immediately but the returned value from test()
will only shown when the click event triggered
Upvotes: 0
Reputation: 1270
As you use it here, withLatestFrom
will always be executed. You don't need logic to check for items, tweak your structure a bit:
@Effect()
updateAfterChanges$ = this.actions$.pipe(
ofType(ActionTypes.ChangesInItems),
switchMap(action => {
return this.store.pipe(
select(fromReducers.getItemsList),
map(items => {
return [new UpdateItems()]
}),
);
}),
)
Upvotes: 1