如何嵌套Reselect选择器?
How to nest Reselect selectors?
我有一个 returns 数组的选择器。数组中的元素本身具有派生数据。我本质上需要一个递归记忆选择器 returns 一个由派生元素组成的派生数组。
我目前的尝试是:
export const selectEntitesWithAssetBuffers = createSelector(
[selectSceneEntities, getAssets],
(entities, loadedAssets) => {
return entities.map((entity) => {
entity.buffers = entity.assets.map((assetName) => {
return loadedAssets[assetName].arrayBuffer;
})
return entity;
})
}
)
我担心的是随时 entities
或 loadedAssets
更改这将重新计算整个列表。我期望设置的是类似于 selectEntityWithBuffer
的东西,它会传递给 entities.map
。理想情况下,我希望它仅在 entity.assets
数组更改时才重新计算。
获得比现有内容更深的记忆是一个棘手的问题,因为 Reselect 并不真正支持将参数传递给选择器。如果您从选择器返回一个数组,并且用于构建该数组的输入已更改,那么您将需要重新计算 Reselect 的预期行为。有关动态参数,请参阅 the advice in the readme。
作为概念证明,我会尝试通过绕过重新选择身份检查.
向结果函数提供 loadedAssets
对象
// Keep a private selector instance
let cachedSelector;
export const selectEntitesWithAssetBuffers = function(){
// loadedAssets should be recalculated on each call?
const loadedAssets = getAssets(arguments);
// create selector on first call
if(cachedSelector === undefined) {
cachedSelector = createSelector(
selectSceneEntities,
entities => {
return entities.map(entity => {
entity.buffers = entity.assets.map((assetName) => {
return loadedAssets[assetName].arrayBuffer;
})
return entity;
})
}
)
}
// Return selector result
return cachedSelector(arguments);
}
Reselect 允许您为选择器提供自定义相等性定义。
import { defaultMemoize, createSelectorCreator } from 'reselect'
const compareByAssets = (a, b) => {
return a.every((element, index) => {
return element.assets === b[index].assets
});
};
const createAssetsComparatorSelector = createSelectorCreator(
defaultMemoize,
compareByAssets
);
const selectSceneEntitiesByAssetsComparator = createAssetsComparatorSelector((state) => {
//however you normally get entities for the pre-existing selectors
});
现在您可以使用这个新的 selectSceneEntitiesByAssetsComparator
代替您提供的上述代码中之前的 selectSceneEntities
并且它只会重新 运行 当平等检查 compareByAssets
失败。
如果 assets === assets
的严格比较不符合您的需要,请随时进一步更新比较器功能。
我有一个 returns 数组的选择器。数组中的元素本身具有派生数据。我本质上需要一个递归记忆选择器 returns 一个由派生元素组成的派生数组。
我目前的尝试是:
export const selectEntitesWithAssetBuffers = createSelector(
[selectSceneEntities, getAssets],
(entities, loadedAssets) => {
return entities.map((entity) => {
entity.buffers = entity.assets.map((assetName) => {
return loadedAssets[assetName].arrayBuffer;
})
return entity;
})
}
)
我担心的是随时 entities
或 loadedAssets
更改这将重新计算整个列表。我期望设置的是类似于 selectEntityWithBuffer
的东西,它会传递给 entities.map
。理想情况下,我希望它仅在 entity.assets
数组更改时才重新计算。
获得比现有内容更深的记忆是一个棘手的问题,因为 Reselect 并不真正支持将参数传递给选择器。如果您从选择器返回一个数组,并且用于构建该数组的输入已更改,那么您将需要重新计算 Reselect 的预期行为。有关动态参数,请参阅 the advice in the readme。
作为概念证明,我会尝试通过绕过重新选择身份检查.
向结果函数提供loadedAssets
对象
// Keep a private selector instance
let cachedSelector;
export const selectEntitesWithAssetBuffers = function(){
// loadedAssets should be recalculated on each call?
const loadedAssets = getAssets(arguments);
// create selector on first call
if(cachedSelector === undefined) {
cachedSelector = createSelector(
selectSceneEntities,
entities => {
return entities.map(entity => {
entity.buffers = entity.assets.map((assetName) => {
return loadedAssets[assetName].arrayBuffer;
})
return entity;
})
}
)
}
// Return selector result
return cachedSelector(arguments);
}
Reselect 允许您为选择器提供自定义相等性定义。
import { defaultMemoize, createSelectorCreator } from 'reselect'
const compareByAssets = (a, b) => {
return a.every((element, index) => {
return element.assets === b[index].assets
});
};
const createAssetsComparatorSelector = createSelectorCreator(
defaultMemoize,
compareByAssets
);
const selectSceneEntitiesByAssetsComparator = createAssetsComparatorSelector((state) => {
//however you normally get entities for the pre-existing selectors
});
现在您可以使用这个新的 selectSceneEntitiesByAssetsComparator
代替您提供的上述代码中之前的 selectSceneEntities
并且它只会重新 运行 当平等检查 compareByAssets
失败。
如果 assets === assets
的严格比较不符合您的需要,请随时进一步更新比较器功能。