2017-09-07 1 views
7

Ich habe einen Selektor, der ein Array zurückgibt. Die Elemente im Array selbst haben abgeleitete Daten. Ich brauche im Wesentlichen einen rekursiven Memo-Selektor, der ein abgeleitetes Array zurückgibt, das aus abgeleiteten Elementen besteht.Wie nistet man Selektoren neu?

mein aktueller Versuch ist:

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

Meine Bedenken sind hier jederzeit entities oder loadedAssets Änderung dieser die gesamte Liste neu berechnet wird. Was ich zu installieren erwarte, ist so etwas wie eine selectEntityWithBuffer, die an die entities.map übergeben werden würde. Im Idealfall möchte ich, dass dies nur neu berechnet wird, wenn sich ein entity.assets Array ändert.

+0

Wenn Sie 'select-map' betrachten, scheint es mit meinen Zielen https://www.npmjs.com/package/reselect-map übereinzustimmen – kevzettler

Antwort

2

Durch erneutes Auswählen können Sie Ihren Selektoren benutzerdefinierte Gleichheitsdefinitionen bereitstellen.

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

Jetzt können Sie diese neue selectSceneEntitiesByAssetsComparator anstelle der vorherigen selectSceneEntities in dem obigen Code verwenden Sie zur Verfügung gestellt, und es wird nur erneut ausgeführt, wenn die Gleichheitsprüfung in compareByAssets ausfällt.

Fühlen Sie sich frei, diese Komparatorfunktion weiter zu aktualisieren, wenn ein strenger Vergleich von assets === assets Ihren Anforderungen nicht entspricht.

0

Eine tiefere Memoisierung als das, was Sie haben, ist ein kniffliges Problem, da Reselect die Übergabe von Argumenten an Selektoren nicht wirklich unterstützt. Wenn Sie ein Array von Ihrem Selektor zurückgeben und die Eingabe, die zum Erstellen dieses Arrays verwendet wurde, sich geändert hat, ist das beabsichtigte Verhalten von Neu auswählen, das Sie erneut berechnen müssen. Für dynamische Argumente siehe the advice in the readme.

3

Als Proof of Concept, ich würde versuchen, loadedAssets Objekt, um die Ergebnis-Funktion von Umgehung erneut Identitätsprüfungen.

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