Как расширить ngrx/data с помощью Entity Effects?

При преобразовании приложения для использования управления состоянием ngrx я решил управлять состоянием некоторых моделей с помощью ngrx/data через EntityMaps. Пока это работает нормально, однако, когда все становится немного сложнее, например, на основе данных модели, полученных с удаленного сервера, мне нужны связанные модели (заказы-> продукты или в формате конечной точки RESTGET orders/:id/products)

Я чувствую себя застрявшим - я знаю, что есть ngrx/effects для запуска действий, которые загружают другие данные при использовании ngrx, и в этом руководстве ngrx/data упоминаются ʻEntityEffects для запуска побочных эффектов с действиями, но кроме этого, документы кажутся в процессе и сейчас мне не очень помогают.

К сожалению, в расширении EntityEffects для настройки получения удаленных данных не так много. Конечно, я мог бы полностью реализовать селекторы, действия, редукторы, эффекты стандартным способом ngrx, но не вся суть ngrx/data в том, чтобы упростить обработку состояния с меньшим количеством шаблонного кода и действовать как оболочка вокруг ngrx, скрывая код по умолчанию / шаблонный код, но при этом предоставляя возможность использовать базовые части?

Поскольку я относительно новичок в ngrx и управлении состоянием в целом, я не знаю, где именно искать лучшие практики или рекомендуемое решение, как решается эта проблема.

Итак, мои вопросы в основном таковы:

  1. Как я могу одновременно использовать ngrx/data и загружать (связанные) данные модели с помощью ngrx/effects или EntityEffects?
  2. Где я могу расширить соответствующие службы / классы, не выполняя каждый редуктор / действие вручную и вместо этого позволяя ngrx/data позаботиться об этом?

Я уже искал Stackru, Gitter и спрашивал коллег, но безуспешно - или я могу сделать это намного сложнее, чем должно быть? Если это так, я благодарен за любую помощь.

Примечание: этот вопрос особенно касается ngrx /

1 ответ

Это открытая проблема с github https://github.com/ngrx/platform/issues/1934


Однако я считаю, что есть способ сделать это, не начиная полностью с нуля, используя EntityCacheDispatcher. saveEntitiesметод Сохранить с помощью EntityCacheDispatcher.saveEntities().

Чтобы дать вам представление о том, как это работает при использовании по назначению, вот мой эффект порядка сохранения в недавнем проекте.

  saveOrder$ = createEffect(() =>
    this.actions$.pipe(
      ofType(PurchaseOrderActions.saveOrder),
      switchMap(() => {
        const order$ = this.store.pipe(select(selectHeader));
        const orderLines$ = this.store.pipe(select(allLines));
        const deletedOrderLines$ = this.store.pipe(select(selectDeletedLines));
        return combineLatest([order$, orderLines$, deletedOrderLines$]).pipe(
          first(),
          switchMap(([order, lines, deletedLines]) => {
            const changes: ChangeSetItem[] = [
              cif.upsert("PurchaseOrder", order),
              cif.upsert("PurchaseOrderLine", lines),
              cif.delete("PurchaseOrderLine", deletedLines)
            ];
            return this.entityCacheDispatcher
              .saveEntities(changes, `${this.baseURL}order`)
              .pipe(
                map(changesResponse =>
                  PurchaseOrderActions.saveOrderSuccess({
                    header: changesResponse.changes[0]
                      .entities[0] as PurchaseOrder,
                    lines: changesResponse.changes[1]
                      .entities as PurchaseOrderLine[]
                  })
                )
              );
          })
        );
      })
    )
  );

Возможная дорожная карта

  1. Создайте собственное действие, например, введите "[OrderProductsPage ONINIT] ONINIT"
  2. Создать эффект, вызывающий saveEntities
// include in custom action payload and get this id here
const id; 

// changeSet with empty changes
const changeSet = {
    changes: [],
    tag: "CUSTOM_GET_PRODUCTS" // hook for defining custom behaviour
}
this.entityCacheDispatcher.saveEntities(changeSet, `orders/${id}/products`)
  1. Расширить EntityCacheDataService и переопределить saveEntities метод, чтобы сначала проверить, является ли тег CUSTOM_GET_PRODUCTSв противном случае вызовите super.saveEntities(changeSet, url). Если тегCUSTOM_GET_PRODUCTS чем вызвать get http и карту каналов для changeSet с помощью ChangeSetOperation.Add

Ссылка на super.saveEntities()

Обновить

Это работает, но немного хитрее, чем мне бы хотелось

Stackblitz

Другие вопросы по тегам