NoneNgrx /data- Как я могу написать собственные редукторы для обработки конечной точки, возвращающей несколько сущностей?

В настоящее время я пытаюсь преобразовать свой магазин ngrx, чтобы использовать ngrx/data для обработки моих сущностей. Одно из самых сложных препятствий, с которыми я столкнулся, - это обработка конечных точек API, которые возвращают данные для нескольких объектов. Простой пример - скажем, у меня есть следующие модели, которые можно получить из моего API:

export interface Parent {
  id: string;
  name: string;
}

export interface Child {
  id: string;
  name: string;
  parent: string
}

И у меня есть следующие конечные точки:

/api/parents              #GET (list of parents), POST (create new parent)
/api/parents/<PARENT_ID>  #GET, PATCH, PUSH, DELETE (a single parent)
/api/children             #GET (list of children), POST (create new child)
/api/children/<CHILD_ID>  #GET, PATCH, PUSH, DELETE (a single child)
/api/families             #GET (all parents and children)

/api/families удобная функция, которая возвращает всех родителей и детей в формате:

{
  parents: Parent[];
  children: Child[];
}

В прошлом я сделал отдельный families запись для моего магазина ngrx с просто загрузкой / загрузкой параметров, затем набор LoadFamilies действия, чтобы получить данные с сервера. Затем я включаю эти действия в редукторы моего магазина "Родители и дети" и действую соответствующим образом. Теперь я хочу добавить этот дополнительный редуктор к моим существующим объектам, контролируемым ngrx/data. Любые мысли / пример кода о том, как пойти по этому поводу?

0 ответов

Расширить DefaultDataServiceсм. https://ngrx.io/guide/data/entity-dataservice

Внутри карты каналов данные вложены в сущности (я использую normalizr)

Затем отправьте действие (я) кеша объекта, используя EntityActionFactory as eaFactory обновить магазин по своему усмотрению

пример с Parent <--> Child of ConcreteRecordHeader <--> ConcreteRecordLoad

  getById(key: string | number): Observable<ConcreteRecordHeader> {
    return super.getById(key).pipe(
      map((denorm: any) =>
        this.categoryCacheService.normalizeCategory([denorm])
      ),
      tap((norm: NormalizedCategories) => this.mergeQuerySet(norm)),
      map((norm: NormalizedCategories) => this.pickEntities(norm)[0])
    ) as Observable<ConcreteRecordHeader>;
  }

  protected mergeQuerySet(norm: NormalizedCategories) {
    console.log("⚠️ Merging server data ⚠️");
    const options: EntityActionOptions = {
      mergeStrategy: MergeStrategy.PreserveChanges
    };
    const data = norm.entities.concreteRecordLoads
      ? Object.values(norm.entities.concreteRecordLoads)
      : [];
    const action = this.eaFactory.create(
      "ConcreteRecordLoad",
      EntityOp.SAVE_UPSERT_MANY_SUCCESS,
      data,
      options
    );
    this.entityCacheDispatcher.dispatch(action);
  }

  protected pickEntities(norm: NormalizedCategories) {
    return (norm.entities.concreteRecordHeaders
      ? Object.values(norm.entities.concreteRecordHeaders)
      : []) as ConcreteRecordHeader[];
  }

Печально this.entityCacheDispatcher.mergeQuerySet()не работает с mergeStrategy, который является естественным API для использования. Я планирую подать на это PR.

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