NgRx Store - условно загружать данные на основе свойства другого объекта состояния - PullRequest
0 голосов
/ 25 июня 2019

У меня есть приложение, которое отображает данные, результаты и т. Д. Из моего API на основе идентификатора сезона - этот идентификатор хранится в состоянии как свойство SeasonState:

export interface SeasonsState extends EntityState<Season> {
  allSeasonsLoaded: boolean;
  currentlySelectedSeasonId: number;
}

Это используется другими компонентами дляопределить, какие приборы, результаты и т. д. нужно извлечь из API и сохранить в состоянии.Например:

this.store
    .pipe(
        select(selectCurrentlySelectedSeason)
    ).subscribe(seasonId => {
  this.store.dispatch(new AllFixturesBySeasonRequested({seasonId}));
  this.fixtures$ = this.store
      .pipe(
          select(selectAllFixturesFromSeason(seasonId))
      );
});

Это хорошо работает, но мне бы очень хотелось, чтобы у меня была возможность только выбирать приборы снова и снова. Светильники для этого конкретного сезона еще не сохранены в состоянии.

Я попытался создать селектор, который будет использоваться для условной загрузки данных из API в моих эффектах:

export const selectSeasonsLoaded = (seasonId: any) => createSelector(
    selectFixturesState,
    fixturesState => fixturesState.seasonsLoaded.find(seasonId)
);

Но я не уверен, как реализовать это / правильный ли это подход.

РЕДАКТИРОВАТЬ: используя информацию из ответа ниже, я написал следующий эффект, однако см. Комментарий - мне нужно иметь возможность использовать seasonId из полезной нагрузки в моем withLatestFrom.

@Effect()
loadFixturesBySeason$ = this.actions$
  .pipe(
      ofType<AllFixturesBySeasonRequested>(FixtureActionTypes.AllFixturesBySeasonRequested),
      withLatestFrom(this.store.select(selectAllFixtures)), // needs to be bySeasonId
      switchMap(([action, fixtures]) => {
          if (fixtures.length) {
              return [];
          }
          return this.fixtureService.getFixturesBySeason(action.payload.seasonId);
      }),
      map(fixtures => new AllFixturesBySeasonLoaded({fixtures}))
  );

1 Ответ

1 голос
/ 25 июня 2019

Настройте свой эффект следующим образом [Я использую ngrx 6, поэтому протестирован на ngrx 6; Если вы используете какую-то другую версию, тогда вы получите представление и измените код соответствующим образом] -

@Effect() allFixturesBySeasonRequested: Observable<Action> =
  this._actions$
      .pipe(
          //Please use your action here;
          ofType(actions.AllFixturesBySeasonRequested),
          //please adjust your action payload here as per your code
          //bottom line is to map your dispatched action to the action's payload
          map(action => action.payload ),
          switchMap(seasonId => {
              //first get the fixtures for the seasonId from the store
              //check its value if there are fixtures for the specified seasonId
              //then dont fetch it from the server; If NO fixtures then fetch the same from the server
              return this.store
                        .pipe(
                            select(selectAllFixturesFromSeason(seasonId)),
                            //this will ensure not to trigger this again when you update the fixtures in your store after fetching from the backend.
                            take(1),
                            mergeMap(fixtures => {
                                //check here if fixtures has something OR have your logic to know
                                //if fixtures are there
                                //I am assuming it is an array
                                if (fixtures && fixtures.lenght) {
                                    //here you can either return NO action or return an action
                                    //which informs that fixtures already there
                                    //or send action as per your app logic
                                    return [];
                                } else {
                                    //NO fixtures in the store for seasonId; get it from there server
                                    return this.http.get(/*your URL to get the fixtures from the backend*/)=
                                               .pipe(
                                                   mergeMap(res => {
                                                        return [new YourFixtureFetchedSucccess()];
                                                    }
                                                   )
                                               )
                                }
                            })
                        );
          })
      )

Теперь вам нужно отправить действие, которое выбирает приборы для указанного сезона из вашего сервиса / компонента или способа разработки вашего приложения.

Надеюсь, это даст вам идею и поможет в решении вашей проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...