Я хочу создать селектор с memoization, используя reselect, основанный на некоторых ownProps
mapStateToProps
.
Как я могу получить ownProps, используя reselect on redux?
Ответ 1
Вы можете сделать это, подключив селектор к компоненту, используя метод connect
предоставленный обработчиком реакции-редукта, затем передайте компонентные реквизиты (ownProps) в качестве второго аргумента в селектор.
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;
Затем вы можете получить доступ к этим реквизитам в своем селекторе
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;
Тем не менее, это не будет memoize правильно, если у вас есть несколько экземпляров компонента, из которого вы передаете реквизиты. В этом случае селектор будет каждый раз получать разные аргументы
props
, поэтому он всегда будет перепрограммировать, а не возвращать кешированное значение.
Чтобы разделить селектор по нескольким компонентам при передаче в реквизитах и сохранении memoization, каждому экземпляру компонента нужна собственная личная копия селектора.
Вы можете сделать это, создав функцию, которая возвращает новую копию селектора при каждом ее вызове.
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;
Если аргумент mapStateToProps
предоставленный для подключения, возвращает функцию вместо объекта, он будет использоваться для создания отдельной функции mapStateToProps
для каждого экземпляра контейнера.
Имея это в виду, вы можете создать функцию makeMapStateToProps
которая создает новый селектор getVisibleTodos
, и возвращает функцию mapStateToProps
которая имеет эксклюзивный доступ к новому селектору:
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;
Теперь каждый экземпляр контейнера VisibleTodosList
получит свою собственную функцию mapStateToProps
с помощью getVisibleTodos
селектора getVisibleTodos
. Memoization теперь будет работать правильно, независимо от порядка отображения контейнеров.
Это было адаптировано (явно скопировано) из документации Reselect