使用带参数的重选选择器

时间:2016-10-27 17:44:35

标签: javascript reactjs ecmascript-6 redux reselect

如何将其他参数传递给组合选择器?我想

•获取数据

•过滤数据

•通过myValue

为我的数据集/组数据添加自定义值
export const allData = state => state.dataTable
export const filterText = state => state.filter.get('text')

export const selectAllData = createSelector(
  allData,
  (data) => data
)

export const selectAllDataFiltered = createSelector(
  [ selectAllData, filterText ],
  (data, text) => {
    return data.filter(item => {
      return item.name === text
    })
  }
)

export const selectWithValue = createSelector(
  [ selectAllDataFiltered ],
  (data, myValue) => {
    console.log(myValue)
    return data
  }
)

let data = selectWithValue(state, 'myValue')

console.log(myValue)返回undefined

6 个答案:

答案 0 :(得分:5)

这是我的方法。使用参数创建函数并返回reselect

export const selectWithValue = (CUSTOM_PARAMETER) => createSelector(
  selectAllDataFiltered,
  (data) => {
    console.log(CUSTOM_PARAMETER)
    return data[CUSTOM_PARAMETER]
  }
)

const data = selectWithValue('myValue')(myState);

答案 1 :(得分:4)

从选择器返回一个函数怎么样? getFilteredToDos就是一个例子

// redux part
const state = {
  todos: [
    { state: 'done',     text: 'foo' },
    { state: 'time out', text: 'bar' },
  ],
};

// selector for todos
const getToDos = createSelector(
  getState,
  (state) => state.todos,
);

// selector for filtered todos
const getFilteredToDos = createSelector(
  getToDos,
  (todos) => (todoState) => todos.filter((toDo) => toDo.state === todoState);
);

// and in component
const mapStateToProps = (state, ownProps) => ({
  ...ownProps,
  doneToDos: getFilteredToDos()('done')
});

答案 2 :(得分:2)

另一种选择:

const parameterizedSelector = (state, someParam) => createSelector(
  [otherSelector],
  (otherSelectorResult) => someParam + otherSelectorResult
);

然后使用

const mapStateToProps = state => ({
  parameterizedSelectorResult: parameterizedSelector(state, 'hello')
});

虽然我不确定这种情况下的记忆/表现,但它确实有用。

答案 3 :(得分:1)

您的问题的答案详见常见问题解答:https://github.com/reactjs/reselect#q-how-do-i-create-a-selector-that-takes-an-argument

简而言之,重新选择不支持传递给选择器的任意参数。建议的方法是,将相同的数据存储在Redux状态,而不是传递参数。

答案 4 :(得分:1)

这里是带有最新useSelector钩子的那个。

重要的是从输入选择器获取参数。输入选择器的第二个参数是我们如何获得它。

选择器的外观如下,

const selectNumOfTodosWithIsDoneValue = createSelector(
  (state) => state.todos,
  (_, isDone) => isDone, // this is the parameter we need
  (todos, isDone) => todos.filter((todo) => todo.isDone === isDone).length
)

这是我们如何使用useSelector钩子提取值的方法,

export const TodoCounterForIsDoneValue = ({ isDone }) => {
  const NumOfTodosWithIsDoneValue = useSelector((state) =>
    selectNumOfTodosWithIsDoneValue(state, isDone)
  )

  return <div>{NumOfTodosWithIsDoneValue}</div>
}

此外,第二个参数(isDone)尽可能保留为primitive values(字符串,数字等)。 因为,重新选择仅在输入选择器值更改时才运行输出选择器。 通过浅层比较检查此更改,对于对象和数组等参考值,该更改始终为false。

参考:

  1. https://react-redux.js.org/next/api/hooks#using-memoizing-selectors
  2. https://flufd.github.io/reselect-with-multiple-parameters/
  3. https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/

答案 5 :(得分:0)

这在 Accessing React Props in Selectors 下的重新选择文档中有介绍:

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(
    [ getVisibilityFilter, getTodos ],
    (visibilityFilter, todos) => {
      switch (visibilityFilter) {
        case 'SHOW_COMPLETED':
          return todos.filter(todo => todo.completed)
        case 'SHOW_ACTIVE':
          return todos.filter(todo => !todo.completed)
        default:
          return todos
      }
    }
  )
}

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

在这种情况下,传递给选择器的 props 是传递给 React 组件的 props,但 props 可以来自任何地方:

const getVisibleTodos = makeGetVisibleTodos()

const todos = getVisibleTodos(state, {listId: 55})

查看下面的 Reselect 类型:

export type ParametricSelector<S, P, R> = (state: S, props: P, ...args: any[]) => R;
export function createSelector<S, P, R1, T>(
  selectors: [ParametricSelector<S, P, R1>],
  combiner: (res: R1) => T,
): OutputParametricSelector<S, P, T, (res: R1) => T>;

我们可以看到 props 的类型没有限制(P 中的 ParametricSelect 类型),所以它不需要是 object