首页 > 解决方案 > Nested store actions not synchronized

问题描述

I'm using NgRx to handle my app state.

I have a mat-slider component to change time on my app.

When user change slider value a list of actual trips get updated on the app state, then shown on a tube map SVG component.

The trips progression is calculated depending on the selected time on slider and the arrival and departure time.

I'm able to do that.

My problem is when I update the selected time. the list of actual trips is not updated quickly on the store so the selected time is get applied on old trips subscribed values , then on new trips values when they get updated on the store.

I think it's an asynchronous problem due to my bad observables implementing, but I can find how to do better.

Here's my implementation

selectedDate$ = this.store.pipe(select(selectDateTimeSelect));
this.selectedDate$
      .pipe(
        switchMap(elm => {
          this.selectedTime = elm.timeSelect; // get actual Time selected
          this.store.dispatch(new GetSchedulesByTime(elm.timeSelect.toString()));
          return this.store.pipe(select(selectSchedulings)); // return new scheduling data ( may be here the update still not happened ? )
        })
      )
      .subscribe((schedules: ISchedule[]) => { // subscribe to that new data
     ..... treatment....
     })

Here's the reducer

case ESchedulesActions.GetSchedulesByTime: {
  let time = action.payload;
  return { ...state, actualTrips: [...(state.schedulings[time] || [])] };
}

Then the selector

export const selectSchedulings = createSelector(
  schedulings,
  (state: ISchedulesState) => state.actualTrips
);

I can't provide a working demo because reproduction is not simple. I think I have provided many elements.

How can I be sure that actual trips are updated before proceeding to treatment ?

Update I'm trying to chain actions inside an effect

$updateActualTrips = createEffect(() =>
  this.actions$.pipe(
    ofType<any>(ESelectDateTimeActionTypes.SetSelectDateTime),
    switchMap(action => ({ type: ESchedulesActions.GetNextSchedulesByTime, payload: action.payload }))
  )
);

But I get this error

Type 'Observable<unknown>' is not assignable to type 'Observable<Action> | ((...args: any[]) => Observable<Action>)'.
  Type 'Observable<unknown>' is not assignable to type 'Observable<Action>'.
    Property 'type' is missing in type '{}' but required in type 'Action'.

标签: angularasynchronousreduxobservablengrx

解决方案


the simplest (but not too pretty) solution would be to

return this.store.pipe(select(selectSchedulings), skip(1));

A prettier solution would be to update schedulings in your store via reducer whenever selectedDate gets changed. This way you don't need to send a separate action for that


推荐阅读