создание селектора @ngrx с данными из нескольких сущностей (Angular)

У меня есть сущности @ngrx, основанные на следующих моделях:

export interface Product {
  id: number;
  code: string;
  text: string;
  brand: any;
  quantity_available: number;
  rate: number;
  // ... other variables
}

export interface BasketProduct {
  id: number; /*Product ID*/
  quantity: number;
  rate: number;
  value: number;
}

Я сохраняю профиль пользователя в состоянии настроек, а выбранные фильтры (поступающие из пользовательского интерфейса) в состоянии продуктов:

export interface State extends EntityState<Setting> {
  // additional properties here
  user: {
    currency: {
      code: string,
      name: string,
    }
  };
}

export interface State extends EntityState<Product> {
  // additional properties here
  filters: {
    just_arrived: boolean;
    newly_launched: boolean;
    discounted: boolean;
    celebrity: boolean;
    niche: boolean;
    wish_list: boolean;
    search_text: string;
    brands;
    product_types;
    parent_companies;
  };
}

Выдержка из моего редуктора выглядит так:

export const selectAllProducts = createSelector(
  selectProductState,
  fromProduct.selectAllProducts
);

export const selectBasketProductEntities = createSelector(
  selectBasketState,
  fromBasket.selectBasketProductEntities
);

export const selectUserProfile = createSelector(
  selectSettingState,
  fromSetting.selectUserProfile
);

export const selectAllFilters = createSelector(
  selectProductState,
  fromProduct.selectAllFilters
);

Затем я создал селектор, который объединяет данные из селекторов выше:

// Returns the List of Products after applying Filters
    export const selectFilteredProducts = createSelector(
      selectAllProducts,
      selectAllFilters,
      selectBasketProductEntities,
      selectUserProfile,
      (products, filters, basket, userProfile) => {
        // Step 1: Filter the Products based on the Parameters
        const filtered = products.filter(
          product =>
            ((filters.just_arrived === false) ||
            (product.is_just_arrived === 1 && filters.just_arrived === true)) &&
            // ..... Additional Filters
        );

        // Step 2: Map the Quantity Selected / Currency Information
        return filtered.map(product => Object.assign({}, product, {
          quantity_selected: basket[product.id],
          currency: userProfile.currency.code
        }));
      }
    );

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

Правильно ли моя реализация карты / фильтра в createSelector? Как я могу улучшить производительность?


person Manish Bhattarai    schedule 11.06.2018    source источник


Ответы (1)


Извините, но другого очевидного решения я не вижу. Если это корзина, то в ней обычно не будет тысячи предметов. Нет? Если да, возможно, вам стоит подумать о фильтрации с помощью бэкэнда.

Однако при обнаружении изменений в Angular производительность может снизиться. Таким образом, вы можете улучшить, предоставив функцию trackBy.

<li *ngFor="let item of collection;trackBy: trackByFn">{{item.id}}</li>

См. этот пост.

С другой стороны, для лучшей читаемости вы можете написать:

return filtered.map(product => {
      ...product,
      quantity_selected: basket[product.id],
      currency: userProfile.currency.code
    }));
person Thierry Falvo    schedule 13.06.2018