I'm trying to build a sequence of RXJS commands in a guard, in order to achieve this result in a simple library (as in books) application :
I've been struggling for a while and looking online does not give an answer according to version 6 of Angular, or standards... What I've succeeded into doing what to create much of it if the store is loaded before hitting the guard, but if it needs to fetch the data, it loops indefinitely.
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this.store.pipe(
select(state => state.books),
tap(state => {
if (!state.loaded) {
this.store.dispatch(new BooksActions.Load());
}
}),
filter(state => state.loaded),
take(1),
map(state => state.list.find(book => book.id === route.params['id'])),
map((book) => {
if(!!book) return true;
this.router.navigate(['/404']);
return false;
})
);
}
Thanks a lot!
The problem is in this section:
select(state => state.books),
tap(state => {
if (!state.loaded) {
this.store.dispatch(new BooksActions.Load());
}
}),
As soon as you dispatch the Load action, most likely your reducer sets the loaded property to false, re-triggering the initial selector, which again triggers the dispatch of the action.
The way I see it, what you need to do is:
This could be archived through the following:
canActivate(route: ActivatedRouteSnapshot): Observable<boolean>
{
return concat(this.loadIfRequired(), this.hasBookInStore(route.params['id'])).pipe(skip(1));
}
private loadIfRequired(): Observable<any>
{
return booksState$.pipe(
map(state => state.loaded),
take(1),
tap(loaded=> {
if (!loaded) {
this.store.dispatch(new BooksActions.Load());
}
}));
}
private hasBookInStore(id: string): Observable<boolean>
{
return this.booksState$.pipe(
first(state => state.loaded),
map(state => state.list.find(book => book.id === id)),
map((book) => {
if(!!book) return true;
this.router.navigate(['/404']);
return false;
})
);
}
private get booksState$(): Observable<BooksState>
{
return this.store.pipe(
select(state => state.books));
}
Let me know if this helps.
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