I have an InitAction
with some params like a profile id and some more data and that action can be called a couple of times with different params.
Besides there is a LoadProfileAction
and I added an effect that is listening to InitAction
and triggers the LoadProfileAction
.
The problem is, that I only want to trigger the LoadProfileAction
, if the profile id had changed compared to the previous one so I think the best(?) solution is to use withLatestFrom
with the store in my effect and check the current profile id.
But it feels wrong to use the store in an effect because it seems to break the flux principle or isn't that true? Are there any better solutions? Thanks!
Now NgRX (v12) provides its own operator for using the store inside an effect. You don't need the two concatMap
, of
, withLatestFrom
solution anymore. Now you can use concatMapFrom
from the @ngrx/effects
library like follows:
import { concatLatestFrom } from '@ngrx/effects';
...
createEffect(() => this.actions$.pipe(
ofType(getSelectedBookDetails),
concatLatestFrom(action => this.store.select(getSelectedBookId)),
switchMap(([action, selectedBookId]) => this.bookService.getDetails(selectedBookId).pipe(
map(...),
catchError(...)
)
);
Bit late to answer this, but maybe it is a help for someone out there. I use NgRX almost everyday and I'd like to share my personal insights.
You can definitely use the store in your effects. You just need to import the store via the constructor (since it is part of the dependency injection tree) and then you can use it in the related effects with the withLatestFrom
RxJS operator. If you read the official docs you will probably see a note on the effects documentation which says
Note: For performance reasons, use a flattening operator in combination with withLatestFrom to prevent the selector from firing until the correct action is dispatched.
So ideally you use the store in the following way:
createEffect(() => this.actions$.pipe(
ofType(getSelectedBookDetails),
concatMap(action => of(action).pipe(
withLatestFrom(this.store.select(getSelectedBookId))
)),
switchMap(([action, selectedBookId]) => this.bookService.getDetails(selectedBookId).pipe(
map(...),
catchError(...)
)
);
Where getDetails()
is an Angular http request and returns an Observable and getSelectedBookId
is an NgRX selector. At least I hope you can get the idea how to use it and that it is not a problem at all to use it in an effect.
You can also be sure that the effect is executed after the reducer has been executed. This order is guaranteed.