2017-07-14 7 views
1

Ich habe einen Reduzierer, der für die Suche verwendet und festgestellt, dass es für mehrere nicht verwandte Suchkomponenten verwendet werden muss. Als ich die Redux-Dokumentation durchblätterte, fand ich das Konzept der Reduktoren höherer Ordnung (http://redux.js.org/docs/recipes/reducers/ReusingReducerLogic.html#customizing-behavior-with-higher-order-reducers) (Meta-Reduzierungen in ngrx) und benutzte das, um 2 'Instanzen' meines Suchreduzierers zu erstellen. Ich fand dann in der gleichen Dokumentation, dass dies scheint, mit Selektoren zu arbeiten, aber tatsächlich ein Problem mit der Memoisierung (http://redux.js.org/docs/recipes/ComputingDerivedData.html#accessing-react-props-in-selectors) hat. Dieser Artikel verweist auf eine Funktion namens "mapStateToProps", die reaktionsspezifisch zu sein scheint, um die Geschäftsdaten mit Komponenten zu verbinden (wenn ich es richtig verstehe ...).Wähler für mehrere Instanzen von NGRX-Reduzierern

Gibt es eine Entsprechung in ngrx oder gibt es eine andere Möglichkeit, diese Selektoren zu erstellen, um mit den verschiedenen Instanzen der Reduzierungen zu arbeiten?

Unten finden Sie eine leicht konstruiertes Beispiel basierend auf dem NGRX Beispiel app von dem, was ich zu tun versuche:

Reduzierungen/searchReducer.ts:

export interface State { 
    ids: string[]; 
    loading: boolean; 
    query: string; 
}; 

const initialState: State = { 
    ids: [], 
    loading: false, 
    query: '' 
}; 

export const createSearchReducer = (instanceName: string) => { 
    return (state = initialState, action: actions.Actions): State => { 
    const {name} = action; // Use this name to differentiate instances when dispatching an action. 
    if(name !== instanceName) return state; 

    switch (action.type) { 
     //... 
    } 
    } 
} 

Minderer/index.ts:

export interface State { 
    search: fromSearch.State; 
} 

const reducers = { 
    search: combineReducers({ 
    books: searchReducer.createReducer('books'), 
    magazines: searchReducer.createReducer('magazines') 
    }), 
} 


export const getSearchState = (state: State) => state.search; 

// (1) 
export const getSearchIds = createSelector(getSearchState, fromSearch.getIds); 

glaube ich, die getSearchIds Wähler über die Fähigkeit benötigt Irgendwie um zu spezifizieren, auf welche Instanz der Suche der Reducer zugreift. (Seltsamerweise in meinem Code scheint zu funktionieren, aber ich bin mir nicht sicher, wie es weiß, aus welchen auszuwählen und ich nehme an, es hat das Memo-Problem in der Redux-Dokumentation diskutiert).

Antwort

0

Während Kevins Antwort für das von mir vorgeschlagene Code-Beispiel sinnvoll ist, gibt es definitiv Wartungsprobleme, wenn jede Reduziererinstanz viele Eigenschaften hat oder viele Instanzen benötigt. In diesen Fällen würden Sie mit vielen quasi-duplizierten Eigenschaften auf einem einzigen Reducer enden (z. B. BookIds, MagazineIds, DvdIds, MicroficheIds usw.).

In diesem Sinne ging ich zurück zu der Redux-Dokumentation und folgte ihm zu den FAQ für Selektoren, speziell How Do I create a Selector That Takes an Argument.

Aus dieser Information, habe ich dies zusammen:

Reduzierungen/index.ts:

export const getBookSearchState = (state: State) => state.search; 
export const getMagazineSearchState = (state: State) => state.search; 

// A function to allow the developer to choose the instance of search reducer to target in their selector. 
export const chooseSearchInstance = (instance: string): ((state: State) => searchReducer.State) => { 
    switch(instance) { 
     case 'books': { 
      return getBookSearchState; 
     } 
     case 'magazines': { 
      return getMagazineSearchState; 
     } 
    } 
} 

// Determines the instance based on the param and returns the selector function. 
export const getSearchIds = (instance: string) => { 
    const searchState = chooseSearchInstance(instance); 
    return createSelector(searchState, state => state.ids); 
} 

In einigen Komponente in dem Sie das Minderer wissen Sie verwenden möchten:

//... 
class SearchComponent { 
    @Input() 
    searchType: string = 'books'; 
    ids: Observable<number>; 

    constructor(private store: Store<fromRoot.State>) {  
     this.store.select(fromRoot.getSearchIds(searchType)); 
    } 
} 
0

Ich würde empfehlen, Ihre Vorgehensweise zu überdenken und den gleichen Reducer zu verwenden und einen weiteren Switch Case zu erstellen.

Unabhängig davon, die neuere Version von AOT nicht gerne mit '=>', um Ihre Reduzierungen zu erstellen. Verwenden Sie stattdessen

export function SearchReducer (state : State = initialState, { type, payload }){ 
    switch (type) { 
     //cases... 
    } 
} 

und Sie werden nicht combineReducers verwenden müssen, können Sie einfach Ihre Aufgabe Minderer bauen aus

let reducers = { 
    search: SearchReducer 
} 

Sagen Sie Ihre Zustand der Schnittstelle Staat Art ist, dass Sie den Vorteil dieser Typisierung nehmen lässt .

+0

Können Sie auf Ihre Antwort erweitern weiteren Schalter Fall machen? Es klingt, als ob Sie beabsichtigen, doppelte Eigenschaften der State-Schnittstelle zu erstellen. Aber das hört sich DRY nicht an, doppelte Eigenschaften zu erzeugen und denselben Kabeljau in verschiedenen Schalteranweisungen zu verwenden. – Mike

+0

Ich denke, es wäre besser, eine zusätzliche Eigenschaft innerhalb eines Reduzierers zu haben, anstatt einen zusätzlichen Reduzierer – Kevin