Вопрос по redux, ngrx, angular – Начните использовать ngrx / эффекты для этого

7

я есть статический набор данных, список стран, которые используются в некоторых компонентах. Эти данные загружаются наngOnInit() из этих компонентов, но я хотел бы загрузить их, только если я впервые запрашиваю данные (хранилище пусто). Каждый раз, когда я загружаю компонент, я хотел бы просто использовать данные из хранилища, не «обновляя» их.

Как это можно сделать с помощью ngrx?

Я использую эффекты. Вот как выглядит мой код:

Компонент:

export class EditPageComponent implements OnInit {
countries$: Observable<Country[]>

constructor(private store: Store<fromContacts.State>) {
    this.countries$ = store.select(fromContacts.getCountriesEntities);
}
ngOnInit() {
   this.store.dispatch(new countries.Load());
}

Эффект:

    @Effect()
      loadCollection$: Observable<Action> = this.actions$
        .ofType(countries.LOAD)
        .switchMap(() =>
          this.countriesService
        .getCountries()
        .map((countriesList: Country[]) => {
          return new countries.LoadSuccess(countriesList);
        })
        .catch(error => of(new countries.LoadFail(error)))
  );

И редуктор:

case countries.LOAD_SUCCESS: {

      const countriesList: Country[] = action.payload;
      const reducedCountries: { [id: string]: Country } = countriesList.reduce((countrs: { [id: string]: Country }, countr: Country) => {
        return Object.assign(countrs, {
            [countr.code]: countr
        });
    }, {});

Спасибо Габ

@ Джим Хороший, я не думал об этом. Работает как шарм gabric
Можете ли вы просто сделать вызов серверу в обработчике «ngOnInit ()» корневого компонента проекта, а не в каждом компоненте, который нуждается в данных? Jim
Ты используешьEffects? Можете ли вы добавить код, куда вы загружаете данные? (не сам сервис, а призыв к нему) maxime1992

Ваш Ответ

3   ответа
5

Есть разные способы сделать это. Прежде всего вы можете сохранитьhasLoaded: boolean собственность в состоянии де. Затем вы можете проверить это, прежде чем позвонить в службу.

ngOnInit() {
  this.store.select(getHasLoaded)
    .take(1)
    .subscribe(hasLoaded => {
      if (!hasLoaded) this.store.dispatch(new countries.Load()); 
    }
}

Другой вариант - позволить вашему @Effect проверять свойство hasLoaded:

@Effect()
  loadCollection$: Observable<Action> = this.actions$
    .ofType(countries.LOAD)
    .withLatestFrom(this.store.select(getHasLoaded)
    .filter(([ action, hasLoaded ]) => !hasLoaded) // only continue if hasLoaded is false 
    .switchMap(() =>
      this.countriesService
        .getCountries()
        .map((countriesList: Country[]) => {
          return new countries.LoadSuccess(countriesList);
        })
    .catch(error => of(new countries.LoadFail(error)))
);

Чтобы это работало, вам нужно предоставить хранилище в конструкторе эффектов.

2
TL; DRиспользованиеtake(1) оператор в эффекте

catchError и вернутьсяEMPTYв противном случае при возникновении ошибки эта ошибка будет возвращаться всегда (таймаут, ошибка аутентификации, автономный режим ...)

У меня был точно такой же случай, как и у вас, я добавлял в эффекты оператор rxjstake выбрать страны только в первый разLoadCountries действие было отправлено.

@Effect()
  loadCountries$: Observable<CoreActions> = this.actions$.pipe(
    ofType(CoreActionTypes.LoadCountries),
    mergeMap(() =>
      this.countriesService.getAllCountries().pipe(
        map(c => new LoadCountriesSuccess(c)),
        catchError(() => {
          this.store.dispatch(new LoadCountriesFailed());
          return EMPTY;
        })
      )
    ),
    take(1)
  );

возвратеEMPTY внутриcatchError завершит наблюдаемое, не проходя черезtake(1)

0

если они представлены в магазине, мы игнорируем действие, если не выбираем страны.

@Effect()
getOrder = this.actions.pipe(
  ofType<GetOrder>(ActionTypes.GetOrder),
  withLatestFrom(this.store.pipe(select(getOrders))),
  filter(([{payload}, orders]) => !!orders[payload.orderId])
  mergeMap([{payload}] => {
    ...
  })
)

Для получения дополнительной информации см.Начните использовать ngrx / эффекты для этого.

Похожие вопросы