最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to nest Reselect selectors? - Stack Overflow

programmeradmin2浏览0评论

I have a selector that returns an array. The elements in the array themselves have derived data. I essentially need a recursive memoization selector that returns a derived array posed of derived elements.

my current attempt is:

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

My concerns here are anytime entities or loadedAssets change this will repute the entire list. What I'm expecting to setup is something like a selectEntityWithBuffer that would get passed to the entities.map. Ideally, I want this to only repute when an entity.assets array changes.

I have a selector that returns an array. The elements in the array themselves have derived data. I essentially need a recursive memoization selector that returns a derived array posed of derived elements.

my current attempt is:

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

My concerns here are anytime entities or loadedAssets change this will repute the entire list. What I'm expecting to setup is something like a selectEntityWithBuffer that would get passed to the entities.map. Ideally, I want this to only repute when an entity.assets array changes.

Share Improve this question edited Sep 18, 2017 at 20:01 kevzettler asked Sep 7, 2017 at 23:38 kevzettlerkevzettler 5,21315 gold badges60 silver badges110 bronze badges 1
  • Looking at reselect-map seems it might be aligned with my goals npmjs./package/reselect-map – kevzettler Commented Sep 9, 2017 at 3:25
Add a ment  | 

3 Answers 3

Reset to default 6 +200

Reselect allows you to provide custom equality definitions to your selectors.

import { defaultMemoize, createSelectorCreator } from 'reselect'

const pareByAssets = (a, b) => {
    return a.every((element, index) => {
        return element.assets === b[index].assets
    });
};

const createAssetsComparatorSelector = createSelectorCreator(
    defaultMemoize,
    pareByAssets
);

const selectSceneEntitiesByAssetsComparator = createAssetsComparatorSelector((state) => {
    //however you normally get entities for the pre-existing selectors
});

Now you can use this new selectSceneEntitiesByAssetsComparator in place of the previous selectSceneEntities in the above code you provided and it will only re-run when the equality check in pareByAssets fails.

Feel free to further update that parator function if a strict parison of assets === assets doesn't suite your needs.

As a proof of concept, I'd try to provide loadedAssets object to the result function by bypassing reselect identity checks.

// 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);
}

Getting deeper memoization than what you've got is kind of a tricky problem because Reselect doesn't really support passing arguments to selectors. If you're returning an array from your selector, and the input used to build that array has changed, it's sort of the intended behavior from Reselect that you will need to repute. See the advice in the readme for dynamic arguments.

发布评论

评论列表(0)

  1. 暂无评论