Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 460
mr__brainwash Avatar asked Jun 07 '18 19:06

mr__brainwash


1 Answers

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.

like image 66
Derek Liang Avatar answered Oct 16 '22 17:10

Derek Liang