Создание селектора @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? Как я могу улучшить производительность?
1 ответ
Извините, но я не вижу другого очевидного решения. Если это корзина, обычно в ней не будет тысячи предметов. Нет? Если да, возможно, вам стоит подумать о фильтрации с бэкэндом.
Однако на производительность может повлиять обнаружение угловых изменений. Таким образом, вы можете улучшить, предоставив 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
}));