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[]);
使用工厂选择器模式 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[]);