【问题标题】:NGRX - combine selectors with propsNGRX - 将选择器与道具结合起来
【发布时间】:2019-02-15 10:19:22
【问题描述】:

当其中一个需要道具时,我如何组合减速器?

我有以下型号:

interface Device {
  id: string;
  data: IDeviceData;
}

以及如下所示的 DeviceReducer:

import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Device } from '../model/device';
import { SubnetBrowserApiActions } from 'src/app/explorer/actions';

export interface State extends EntityState<Device> { }

export const adapter: EntityAdapter<Device> = createEntityAdapter<Device>();

export const initialState: State = adapter.getInitialState();

export function reducer(
  state = initialState,
  action:
    | SubnetBrowserApiActions.SubnetBrowserApiActionsUnion
): State {
  switch (action.type) {
    case SubnetBrowserApiActions.SubnetBrowserApiActionTypes.LoadEntriesSucces: {
      return adapter.upsertMany(action.payload.entries, state);
    }

    default: {
      return state;
    }
  }
}

const {
  selectAll,
} = adapter.getSelectors();

export const getAllDevices = selectAll;

在我的另一个减速器中,当我想使用 id 数组选择设备时,我使用以下代码:

export const getVisibleDrives = createSelector(
  [fromRoot.getAllDevices, getVisibleDrivesSerialNumbers],
  (devices, visibleDevicesIds) =>
    devices.filter((device) => onlineDevicesIds.includes(device.serialNumber)),
);

这段代码非常重复,所以我想添加参数化选择器,它将只返回这些驱动器,它们在数组中具有我作为道具传递的 id。我尝试做的看起来如下:

DeviceReduced 中的附加选择器

export const getDrivesWithIds = (ids: string[]) => createSelector(
  getAllDevices,
  devices => devices.filter(device => ids.includes(device.id))
);

然后以以下的方式将它们组合起来:

export const getVisibleDrives = createSelector(
  getVisibleDrivesSerialNumbers,
  (ids) => fromRoot.getDrivesWithIds
);

这里的问题是这个选择器的返回类型是

(ids: string[]) =&gt; MemoizedSelector&lt;State, Device[]&gt;

这让我无法用这个选择器做任何有用的事情。例如,我想按关键字过滤此列表,但我无法在其上使用 filter 方法:

使用示例

export const getFilteredVisibleDrives = createSelector(
  [getVisibleDrives, getKeywordFilterValue],
  (visibleDrives, keywordFilter) => {
    return visibleDrives
      .filter(drive => // in this line there is an error: Property 'filter' does not exist on type '(ids: string[]) => MemoizedSelector<State, Device[]>'
        drive.ipAddress.toLowerCase().includes(keywordFilter.toLowerCase()) ||
        drive.type.toLowerCase().includes(keywordFilter.toLowerCase()) ||
        drive.userText.toLowerCase().includes(keywordFilter.toLowerCase())
      );
  },
);

【问题讨论】:

    标签: ngrx ngrx-store


    【解决方案1】:

    看我的帖子NgRx: Parameterized selectors 了解更多信息。

    更新:NgRx v13+

    不推荐使用带有 props 的选择器,请改用选择器工厂:

    选择器:

    export const getCount = (props: {id: number, multiply:number}) =>   
      createSelector(     
        (state) => state.counter[props.id],     
        (counter) => counter * props.multiply
      );
    

    组件:

    this.counter2 = this.store.pipe(
      select(fromRoot.getCount({ id: 'counter2', multiply: 2 })
    );   
    this.counter4 = this.store.pipe(
      select(fromRoot.getCount({ id: 'counter4', multiply: 4 })
    );
    

    已弃用

    选择器:

    export const getCount = () =>   
      createSelector(     
        (state, props) => state.counter[props.id],     
        (counter, props) => counter * props.multiply
      );
    

    组件:

    this.counter2 = this.store.pipe(
      select(fromRoot.getCount(), { id: 'counter2', multiply: 2 })
    );   
    this.counter4 = this.store.pipe(
      select(fromRoot.getCount(), { id: 'counter4', multiply: 4 })
    );
    

    【讨论】:

    • 在您可能在“功能”级别定义减速器然后在功能之外将它们设为全局的情况下如何工作?我试过了,但它不起作用:gist.github.com/mindscratch/22d507f8401dc9f78627db8c61b3f931
    • @timdeschryver - 您能否更新您的答案以包含 v13 的语法,其中选择器道具已被弃用!
    • 感谢@AakashGoplani - 它已更新。
    猜你喜欢
    • 2021-12-14
    • 2018-09-22
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多