Je veux créer un sélecteur avec mémorisation en utilisant reselect basé sur certains ownProps
de mapStateToProps
.
Vous pouvez le faire en connectant le sélecteur à un composant à l'aide de la méthode connect
fournie par react-redux , puis en passant les accessoires du composant (ownProps) comme deuxième argument au sélecteur.
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;
Vous pouvez ensuite accéder à ces accessoires dans votre sélecteur
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;
Cependant, cela ne mémorisera pas correctement si vous avez plusieurs instances du composant à partir duquel vous passez des accessoires. Dans ce cas, le sélecteur recevrait un argument
props
différent à chaque fois, il recalculerait donc toujours au lieu de renvoyer une valeur mise en cache.
Pour partager un sélecteur entre plusieurs composants tout en passant des accessoires et conservant la mémorisation, chaque instance du composant a besoin de sa propre copie privée du sélecteur.
Vous pouvez le faire en créant une fonction qui renvoie une nouvelle copie du sélecteur à chaque appel.
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;
Si l'argument mapStateToProps
fourni pour se connecter renvoie une fonction au lieu d'un objet, il sera utilisé pour créer une fonction mapStateToProps
individuelle pour chaque instance du conteneur .
Dans cet esprit, vous pouvez créer une fonction makeMapStateToProps
qui crée un nouveau sélecteur getVisibleTodos
et renvoie une fonction mapStateToProps
qui a un accès exclusif au nouveau sélecteur:
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;
Maintenant, chaque instance du conteneur VisibleTodosList
aura sa propre fonction mapStateToProps
avec un sélecteur getVisibleTodos
privé. La mémorisation fonctionnera désormais correctement quel que soit l'ordre de rendu des conteneurs.
Ceci a été adapté (copié de manière flagrante) de la Resélectionnez la documentation