2017-06-26 2 views
0

Ich habe einen redux Zustand mit einem Baum der Elemente (normalisiert) wie:Reselect und rekursive Wähler

state = { 
    items: [ 
    { id: 1, parent: null, children: [2, 3] }, 
    { id: 2, parent: 1, children: [4] }, 
    { id: 3, parent: 1, children: [], value: 10 }, 
    { id: 4, parent: 2, children: [], value: 20 } 
    ] 
} 

ich die Verringerung Summe der Werte für Punkt 1 (hier = 10 + 20 = 30) erhalten möchten und ich möchte einen Selector Selector dafür erstellen.

Aber wie kann ich einen rekursiven Selektor definieren?

Danke für Ihre Hilfe. ;-)

Frédéric

+0

was meinst du mit „einer Neuauswahl Selektor erstellen“? – Vanojx1

+0

Ich meine, das Ergebnis des "Getter" aus dem Staat mit: https://github.com/reactjs/reselect –

Antwort

0

Versuchen Sie folgendes:

let state = { 
 
    items: [ 
 
     { id: 1, parent: null, children: [2, 3] }, 
 
     { id: 2, parent: 1, children: [4] }, 
 
     { id: 3, parent: 1, children: [], value: 10 }, 
 
     { id: 4, parent: 2, children: [], value: 20 } 
 
    ] 
 
} 
 

 
function getSum(state, id) { 
 
    let item = state.items.find(item => item.id == id); 
 
    return item.hasOwnProperty('value') ? item.value : item.children.reduce((current, next) => { 
 
    return current + getSum(state, next); 
 
    }, 0); 
 
} 
 

 
let sum = getSum(state, 1); 
 

 
console.log(sum);

+0

Memoize für Ihre Hilfe, aber ich möchte wieder mit Redux auswählen, um das Ergebnis zu merken UND zu reset der Cache, wenn ein Elementwert in der Struktur aktualisiert wird –

1

I @ Vanojx1 Code aktualisiert werden 2 Lösungen vorzuschlagen:

(Disclaimer: Ich bin der Autor wieder neu wählen, aber dies ist ein typischer Anwendungsfall)

Code-Basis

let state = { 
    items: [ 
     { id: 1, parent: null, children: [2, 3] }, 
     { id: 2, parent: 1, children: [4] }, 
     { id: 3, parent: 1, children: [], value: 10 }, 
     { id: 4, parent: 2, children: [], value: 20 } 
    ] 
}; 

function getSum(items, id) { 
    let item = items.find(item => item.id == id); 
    return item.hasOwnProperty('value') ? item.value : item.children.reduce((current, next) => { 
    return current + getSum(items, next); 
    }, 0); 
} 

Lösung 1 - nur

import { createSelector } from 'reselect'; 

const getSumSelector = createSelector(
    (state) => state.items, 
    (state, id) => id, 
    (items, id) => getSum(items, id) 
); 

getSumSelector(state, 1); 
// Loses memoization with sequentials calls with same items but different id's 
erneut auswählen

Lösung - erneut auswählen + Wieder erneut auswählen

import createCachedSelector from 're-reselect'; 

const getSumSelector = createCachedSelector(
    state => state.items, 
    (state, id) => id, 
    (items, id) => getSum(items, id) 
)(
    // Cache selector by id 
    (state, id) => id 
); 

getSumSelector(state, 1); 
+0

thanks; Mit Ihrer Lösung habe ich eine Frage: Wenn der Baum geändert wird, wird der Selektor auch aktualisiert? –

+0

Selektoren sind reine Funktionen und Sie müssen die erforderlichen Argumente bei jedem Aufruf übergeben. Bitte beachten Sie, dass die '' select''-Standardmemotisierung nur eine Gleichheitsprüfung durchführt, um festzustellen, ob die Argumente dem letzten Aufruf entsprechen ('previousState' ===' providedState'). –