如何创建选择器以从ngrx商店中按ID选择项目

Ole*_*nko 11 typescript ngrx ngrx-store

我阅读了ngrx商店关于选择器的文档,并且需要弄清楚如何创建选择器以便按项目ID选择一个项目.当我从selectAllItems选择器中获取所有项目时,我已经可以将此作为商店订阅的一部分,但我需要弄清楚如何从商店中的项目列表中选择特定项目.我的主要原因是createSelector提供了我喜欢的性能提升.

这是我的代码:

import { AppState, Item } from '../../shared/models/index';
import { createSelector } from '@ngrx/store';

export const selectItems = (state: AppState) => state.eventsState;

export const selectAllItems = createSelector(selectItems, (allItems: { items: Item[] }) => {
  if (allItems && allItems.items) {
   return allItems.items.filter((item: Item) => (!item.active && !item.closed));
  } else {
    return allItems.items;
  }
});
Run Code Online (Sandbox Code Playgroud)

然后在我的控制器中我按ID过滤以获得所需的项目:

this.store.select(selectors.selectAllItems)
  .filter(data => data !== null)
  .subscribe(allItems => {
    this.item = allItems.filter(item => {
      return item.id === this.navParams.data.id;
    });
  });
Run Code Online (Sandbox Code Playgroud)

我希望能够为该特定项创建一个选择器,并像这样使用它:

this.store.select(selectors.selectItemById(this.navParams.data.id))
  .filter(data => data !== null)
  .subscribe(selectedItem => {
    this.item = selectedItem;
  });
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激.

Ole*_*nko 21

经过一番研究,我解决了自己的问题.我使用工厂函数来获得所需的selectItemById选择器.这是我的新选择器:

import { AppState, Item } from '../../shared/models/index';
import { createSelector } from '@ngrx/store';

export const selectItems = (state: AppState) => state.eventsState.items;

export const getItemById = (id) => createSelector(selectItems, (allItems) => {
  if (allItems) {
    return allItems.find(item => {
      return item.itemId === id;
    });
  } else {
    return {};
  }
});
Run Code Online (Sandbox Code Playgroud)

然后我在我的控制器中所做的就是调用这个选择器并将它传递给所需项目的id以将该项目从商店中取出:

import * as selectors from '../../app/store/selectors';

this.store.select(selectors.getItemById(id))
  .subscribe((item) => {
    this.item = item;
  });
Run Code Online (Sandbox Code Playgroud)

  • 如果您将实体存储为基于 id 的哈希表,您的访问将是 O(1) 而您根本不必循环避免 O(n)。 (2认同)

Mak*_*nko 8

使用实体时,一切都会变得更加容易。当您将它们存储为对象时,其中key是id项目的一个,而value是项目本身的。有两种方法可以将项目保留为数组-仅存储ID或项目的完整对象。

在减速器中:

export interface ItemsState {
  loaded: boolean;
  loading: boolean;
  items: { [key: string]: Item };
  itemIds: any[];
}

const initialState: ItemsState = {
  loaded: true,
  loading: false,
  items: {
    0: {
      foo: 'bar'
    },
    1: {
      bar: 'foo'
    }
  },
  itemIds: [0, 1]
}
Run Code Online (Sandbox Code Playgroud)

在选择器中:

export const getItems = (state: ItemsState) => state.items;

export const getItemById = (id) => createSelector(
  getItems, 
  (items) => items[id]
);
Run Code Online (Sandbox Code Playgroud)

在容器(组件)中:

constructor(
  private store: Store,
  private route: ActivatedRoute
) {}

getItemOnInit(): void {
  // or any other way to retrieve id from route
  const id = this.route.snapshot.params.id;
  this.store.pipe(select(getItemById(id)));
}
Run Code Online (Sandbox Code Playgroud)