【问题标题】:How to nest Reselect selectors?如何嵌套重新选择选择器?
【发布时间】:2017-09-07 23:38:36
【问题描述】:

我有一个返回数组的选择器。数组中的元素本身具有派生数据。我本质上需要一个递归记忆选择器,它返回一个由派生元素组成的派生数组。

我目前的尝试是:

export const selectEntitesWithAssetBuffers = createSelector(
  [selectSceneEntities, getAssets],
  (entities, loadedAssets) => {
    return entities.map((entity) => {
      entity.buffers = entity.assets.map((assetName) => {
        return loadedAssets[assetName].arrayBuffer;
      })
      return entity;
    })
  }
)

我在这里担心entitiesloadedAssets 随时更改这将重新计算整个列表。我期望设置的是类似于selectEntityWithBuffer 的东西,它会被传递给entities.map。理想情况下,我希望仅在 entity.assets 数组更改时重新计算。

【问题讨论】:

标签: javascript reactjs redux reselect


【解决方案1】:

重新选择允许您为选择器提供自定义相等定义。

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 的严格比较不能满足您的需求,请随时进一步更新该比较器功能。

【讨论】:

    【解决方案2】:

    作为概念证明,我会尝试通过绕过重新选择身份检查,将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);
    }
    

    【讨论】:

      【解决方案3】:

      获得比你所拥有的更深入的记忆是一个棘手的问题,因为 Reselect 并不真正支持将参数传递给选择器。如果您从选择器返回一个数组,并且用于构建该数组的输入已更改,那么您将需要重新计算来自 Reselect 的预期行为。有关动态参数,请参阅 the advice in the readme

      【讨论】:

        猜你喜欢
        • 2018-08-10
        • 2012-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-14
        相关资源
        最近更新 更多