i'm new in angular 6 and ngrx store. I try to dispatch action after get data subscribe from store but it make infinite loop and crash browser? What i was wrong . Some solution i find it using do/tap operator of rxjs but still not working. And when i use {{(feedState | async).loading}} for example , it alway return undefined .
my component:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.feedSubscription = this.store
.pipe(
select('feed'),
map(data => {
this.feedState = data;
return data.categories;
}),
tap(data =>
this.store.dispatch(
new FeedActions.GetFeedItems({
cat_id: data[this.selectedIndex],
page: 0
})
)
)
)
.subscribe(data => {});
}
The select operator will create an observable which emits every time the state of 'feed' is updated. This will fire the first time when you do your FeedActions.GetFeedCategories()
but it will also fire again when the result of FeedActions.GetFeedItems(...)
is added to the state, which will cause FeedActions.GetFeedItmes(...)
to be executed again, and again, and again...
The simple solution is to add a take(1) into the pipe, so you only get a single fire of the map and tap operators:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.feedSubscription = this.store
.pipe(
select('feed'),
take(1),
map(data => {
this.feedState = data;
return data.categories;
}),
tap(data =>
this.store.dispatch(
new FeedActions.GetFeedItems({
cat_id: data[this.selectedIndex],
page: 0
})
)
)
)
.subscribe(data => {});
}
However, it may be worth considering splitting the concerns here - you've mixed the job of preparing the state with the job of selecting the state for display. A better solution may be something like this:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.store.pipe(
select('feed'),
take(1),
map(data => data.categories),
tap(data =>
this.store.dispatch(
new FeedActions.GetFeedItems({
cat_id: data[this.selectedIndex],
page: 0
})
)
)
)
.subscribe(() => {});
this.feedState = this.store.pipe(
select('feed')
);
}
... then in your template, you can use {{feedState | async}}?.loading
or whatever as needed.
The async
pipe does the subscription for you and expects an observable, not a raw data field. In your example, this.feedState should be of type Observable<FeedState>
, but it looks to be a raw data type (e.g. FeedState instead of Observable) from the code provided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With