NGRX 选择器:在 createSelector 方法中没有 prop 的另一个选择器中的工厂选择器

NGRX selectors: factory selector within another selector without prop in createSelector method

使用工厂选择器模式 const selectA = (id: number) => createSelector(...) 我有一个实例,我想在另一个选择器(遍历 ID 数组)中重用这个选择器,但我不知道要传递给调用 createSelector.

时的因子选择器

所以我有一个选择器,每当我想获取组件 A 的状态片段时都会使用它。

const selectA = (id: number) =>
    createSelector(
        selector1.selectEntityMap,
        selector2.selectEntityMap,
        selector3ById(id), 
        (
        thing1, 
        thing2, 
        thing3
        ) => {
            return ...
       });

现在我想获取数组中每一项的组件 A 列表。

const selectListOfA = (ids: number[]) =>
    createSelector(
    selectA, 
    (selectorA) => {
        return ids.map((id) => selectorA(id));
    });

问题是selectA,现在是一个工厂选择器,需要一个参数,但是调用createSelector的时候不知道。

我可以通过在工厂上创建另一个工厂来获取要编译的代码 const selectAFactory = () => selectA;

然后在createSelector

中引用新工厂
const selectListOfA = (ids: number[]) =>
    createSelector(
    selectAFactory, <<< here 
    (selectorA) => {
        return ids.map((id) => selectorA(id));
    });

但是当然,现在发生的是选择器返回 MemoizedSelector[].

的列表

这个模式看起来不应该这么复杂,人们不是以这种方式重用他们的选择器吗,我错过了什么?

selectA 编写的函数 return 是一个标准函数,即它没有什么神奇之处,正如这篇博客 post 中所解释的那样: https://dev.to/zackderose/ngrx-fun-with-createselectorfactory-hng

这意味着 selectListOfA 可以简单地从 selectA 为每个 id 调用函数 returned 并且组件 A 的状态切片数组将被 returned :

export const selectListOfA = (ids: number[]) =>
  createSelector(
    (state) => state,
    (state) => ids.map((id) => selectA(id)(state))
  );

这按预期工作,但由于每次商店中的任何内容发生变化时都会执行投影仪功能(为每个 id 重新创建选择器),此解决方案将存在重大性能问题。

我们也可以将代码简化为同样糟糕的性能:

const selectListOfA = (ids: number[]) =>
  (state) => ids.map(
    (id: number) => selectA(id)(state)
  );

如果我们改为提供选择器数组作为 createSelector 调用的输入,那么 Ngrx 将能够正确确定何时必须重新评估 selectA 选择器:

const selectListOfA = (ids: number[]) =>
  createSelector(
    ids.map((id) => selectA(id)), // This results in an array of selectors
    (...resultArr) => resultArr
  );

但是,Typescript 会报错,因为 createSelector 方法没有为可变长度数组声明的匹配重载,因此我们需要放宽数组的输入类型(到 any)以及指定 return 类型 selectListOfA.

问题的答案是:

  const selectListOfA = (ids: number[]) =>
  (createSelector(
    ids.map((id) => selectA(id)) as any,
    (...resultArr) => resultArr
  ) as (state) => string[]);