2016-04-03 18 views

risposta

17

È possibile eseguire questa operazione collegando il selettore a un componente utilizzando il metodo connect fornito da react-redux, quindi passando il componente props (ownProps) come secondo argomento al selettore.

container.js

import { connect } from 'react-redux'; 
import { getVisibleTodos } from './selectors'; 

... 

const mapStateToProps = (state, props) => { 
    return { 
    todos: getVisibleTodos(state, props), 
    }; 
}; 

const VisibleTodoList = connect(
    mapStateToProps, 
)(TodoList); 

export default VisibleTodoList; 

È quindi possibile accedere a tali puntelli nella vostra selettore

selectors.js

import { createSelector } from 'reselect'; 

const getVisibilityFilter = (state, props) => 
    state.todoLists[props.listId].visibilityFilter; 

const getTodos = (state, props) => 
    state.todoLists[props.listId].todos; 

const getVisibleTodos = createSelector(
    ... 
); 

export default getVisibleTodos; 

Howeve r, questo sarà non memoize correttamente se si dispone di più istanze del componente da cui si passano gli oggetti di scena. In tal caso, il selettore riceverebbe un diverso argomento props ogni volta, pertanto verrà sempre ricalcolato anziché restituire un valore memorizzato nella cache.

Per condividere un selettore su più componenti mentre passando puntelli e ritegno Memoizzazione, ogni istanza del componente ha bisogno la propria copia privata del selettore.

È possibile eseguire questa operazione creando una funzione che restituisce una nuova copia del selettore ogni volta che viene chiamato.

selectors.js

import { createSelector } from 'reselect'; 

const getVisibilityFilter = (state, props) => 
    state.todoLists[props.listId].visibilityFilter; 

const getTodos = (state, props) => 
    state.todoLists[props.listId].todos; 

const makeGetVisibleTodos =() => { 
    return createSelector(
    ... 
); 
} 

export default makeGetVisibleTodos; 

Se l'argomento mapStateToProps fornito per collegare i ritorni una funzione invece di un oggetto, sarà usato per creare un individuo funzione mapStateToProps per ogni istanza del contenitore.

Con questo in mente, è possibile creare una funzione di makeMapStateToProps che crea un nuovo selettore getVisibleTodos, e restituisce una funzione mapStateToProps che ha accesso esclusivo al nuovo selettore:

import { connect } from 'react-redux'; 
import { makeGetVisibleTodos } from './selectors'; 

... 

const makeMapStateToProps =() => { 
    const getVisibleTodos = makeGetVisibleTodos(); 
    const mapStateToProps = (state, props) => { 
    return { 
     todos: getVisibleTodos(state, props), 
    }; 
    }; 
    return mapStateToProps; 
}; 

const VisibleTodoList = connect(
    makeMapStateToProps, 
)(TodoList); 

export default VisibleTodoList; 

Ora ogni istanza del VisibleTodosList contenitore avrà la propria funzione mapStateToProps con un selettore privato getVisibleTodos. La Memoizzazione ora funzionerà correttamente indipendentemente dall'ordine di rendering dei contenitori.


Questo è stato adattato (blatently copiato) dal Reselect documentation

+0

Ciao, ho una domanda su questo: che cosa succede se voglio aggiungere parametri makeGetVisibleTodos()? Diciamo che ho due componenti che usano lo stesso selettore di parametri, ma la loro denominazione di oggetti di scena è diversa, in questo caso non funzionerà perché i sottostanti 'getTodos' e' getVisibilityFilter' falliranno. Esempio: 'betterFoobar = (id) => createSelector (foobarSelector, (foobarValue) => id + foobarValue)' La mia idea finora: 'mapStateToProps = createStructuredSelector ({enhancedFooBar: (stato, ownProps) => betterFoobar (ownProps.id) (state, ownProps)}) 'ma immagino che questo non verrà memoize. –

+0

Per rendere più chiaro il mio punto, pongo questa domanda perché fare affidamento su ownProps in un selettore accoppia strettamente un'API del componente React con un selettore di stato Redux. Ciò rende i selettori non utilizzabili tra i componenti, mentre sono uno strumento di riutilizzabilità estremamente potente. Ad esempio, mi piacerebbe utilizzare i miei selettori sia nel processo principale che nel processo di rendering di un elettrone e in più componenti. La soluzione accettata sembra non essere adatta in questo caso (ma ovviamente risponde alla domanda iniziale e potrebbe aver bisogno solo di alcune modifiche per funzionare nei miei casi d'uso). –