web-dev-qa-db-fra.com

Comment puis-je obtenir ownProps en utilisant reselect sur redux?

Je veux créer un sélecteur avec mémorisation en utilisant reselect basé sur certains ownProps de mapStateToProps.

19

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

25
Seth