Search code examples
angularreduxrxjsngrxngrx-store

How to dispatch an action with current value of state?


I have an angular component showing items in a list. Each itemn can be selected and the ids of the selected items will be stored in the state. So my state object looks like this f.e.:

{ items: Item[]; selected: string[] }

Now I got an action called DeleteSelectedAction that gets selected as payload. This action will call some WebAPI using an effect and so on.

Now I found two ways how I could do this.

First: Select selected from store and subscribe to it and pass the value with the action

store.select(fromItems.getSelected).subscribe(ids => {
    this.selected = ids; 
});
...
store.dispatch(new itemActions.DeleteSelectedAction(this.selected);

Second: Pass no value to action but fetch the selected in effect

store.dispatch(new itemActions.DeleteSelectedAction());

// in effect
@Effect()
delete$: Observable<Action> = this.actions$
  .ofType(fromItems.DELETE)
  .withLatestFrom(this.store.select(fromItems.getSelected)
  .switchMap([action, selected] => {
    return this.service.delete(selected)
      .map(new itemActions.DeleteSuccessAction())
      .catch(err => Observable.of(new itemActions.DeleteFailAction(err));
  });

I don't like the first way because I need to use a subscription and need to unsubscribe properly. The second way is ok but only when the action has side effects. So now I'm looking for a third way. In my head this way looks like the following:

store.dispatchWithLatestFrom(
  fromItems.getSelected,
  (selected) => new itemActions.DeleteSelectedAction(selected));

How could I get something like that with rxjs operators?


Solution

  • Your second approach should work just fine even if the action has no side effects. using an @Effect to transform an action without performing a side effect is a perfectly legitimate use of the library. See the section on Content Enrichers here. In that case, I'd definitely call the action something like DELETE_SELECTED rather than just DELETE.