mr__brainwash
mr__brainwash

Reputation: 1382

Proper way to access store in ngrx/effect

I am using Angular 6, ngrx/store, ngrx/effects. I have an effect that should be triggered when i press "Save" button. I am using withLatestFrom there to collect all data what i need for sending it to the server:

@Effect({dispatch: false})
  saveAll$ = this.actions$.pipe(
    ofType(ActionTypes.Save),
    withLatestFrom(
      this.store.select(fromReducers.getData1),
      this.store.select(fromReducers.getData2),
      this.store.select(fromReducers.getData3),
      this.store.select(fromReducers.getData4)
    ),
    switchMap(([action, data1, data2, data3, data4]: [ActionType, Data1[], Data2[], Data3[], Data4[]]) => {
       // here is some operations with these data
       return this.apiService.saveData({data1, data2, data3, data4})
    })
)

Here is getData1 selector:

export const getData1= createSelector(
  getItems,
  getIndexes,
  (items, indexes) => {
    console.log('HI, I AM getData1');
    return transformItems(items, indexes);
  }
);

getItems, in turn, return state.items. The problem is that state.items can be modified in another effect:

@Effect()
  handleItemsChanges$ = this.actions$.pipe(
    ofType(ActionTypes.ChangesInItems),
    withLatestFrom(
      this.store.select(fromReducers.getItems),
      this.store.select(fromReducers.getUsers),
    ),
    switchMap(([action, items, users]: [ActionType, Item[], User[]]) => {
       console.log('I AM handleItemsChanges');
       const actions = [];
       if (itemsShouldBeUpdated) {
          actions.push(new UpdateData(changes))
       }
    })
)

So getData1 selector gets data from the store depend on another effect named handleItemsChanges. handleItemsChanges effect is triggered every time something is changed related to the items and recalc it again. As a result, in saveAll i am getting not actual state.items. What am i doing wrong? May be i should use another operator insted of withLatestFrom or what ca be the solution? Thank you

P.S. Btw i am using withLatestFrom every time when i want to get some data from the store. Is it correct?

Upvotes: 9

Views: 13061

Answers (2)

Mihail
Mihail

Reputation: 471

I've found discussion on ngrx github : https://github.com/ngrx/platform/issues/467 Looks like we have 2 ugly variants for accessing store from effects now.

Upvotes: 1

Derek Liang
Derek Liang

Reputation: 1222

you need to have action handleItemsChanges fired before saveAll gets fired. One way to do it is to create an effect on handleItemsChanges action and trigger the save action.

The framework will guarantee the order of execution (handleItemsChanges first then save), this way the withLatestFrom operation will work as you expected.

Upvotes: 2

Related Questions