如何将附加参数传递给组合选择器?我正在努力
• 获取数据
• 过滤数据
• 通过 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
更新日期:2023 年 12 月 4 日
与 4.1 相比没有变化,但是 使用 Typescript 更新了 5.0.0 版本的文档。请阅读文档以了解有关特殊情况的更多详细信息。
// selector.ts
const selectAvailableItems = createSelector(
[
// First input selector extracts items from the state
(state: RootState) => state.items,
// Second input selector forwards the category argument
(state: RootState, category: string) => category,
// Third input selector forwards the ID argument
(state: RootState, category: string, id: number) => id
],
// Output selector uses the extracted items, category, and ID
(items, category, id) =>
items.filter(item => item.category === category && item.id !== id)
)
interface RootState {
items: {
id: number
category: string
vendor: { id: number; name: string }
}[]
// ... other state properties ...
}
// App.tsx
const items = selectAvailableItems(state, 'javascript', 10);
// Another way if you're using redux hook:
const items = useSelector(state => selectAvailableItems(state, 'javascript', 10));
更新日期:2022 年 2 月 16 日
// selector.js
const selectItemsByCategory = createSelector(
[
// Usual first input - extract value from `state`
state => state.items,
// Take the second arg, `category`, and forward to the output selector
(state, category) => category
],
// Output selector gets (`items, category)` as args
(items, category) => items.filter(item => item.category === category)
);
// App.js
const items = selectItemsByCategory(state, 'javascript');
// Another way if you're using redux hook:
const items = useSelector(state => selectItemsByCategory(state, 'javascript'));
更新日期:2021 年 3 月 6 日
// selector.js
import { createSelector } from 'reselect'
import memoize from 'lodash.memoize'
const expensiveSelector = createSelector(
state => state.items,
items => memoize(
minValue => items.filter(item => item.value > minValue)
)
)
// App.js
const expensiveFilter = expensiveSelector(state)
// Another way if you're using redux:
// const expensiveFilter = useSelector(expensiveSelector)
const slightlyExpensive = expensiveFilter(100)
const veryExpensive = expensiveFilter(1000000)
旧:
这是我的方法。创建一个带有参数和返回函数reselect
的函数。
export const selectWithValue = (CUSTOM_PARAMETER) => createSelector(
selectAllDataFiltered,
(data) => {
console.log(CUSTOM_PARAMETER)
return data[CUSTOM_PARAMETER]
}
)
const data = selectWithValue('myValue')(myState);
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
)保留为原始值(字符串、数字等)。 因为,reselect 仅在输入选择器值更改时运行输出选择器。 此更改是通过浅比较来检查的,对于对象和数组等参考值来说,浅比较始终为 false。 参考资料:
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')
});
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})
查看以下重新选择的类型:
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>;
我们可以看到道具的类型没有限制(P
中的
ParametricSelect
类型),所以它不需要是
object
。
createSelector
不同):
const pokemon = useSelector(selectPokemonById(id));
import memoize from 'lodash.memoize';
import { createSelector } from '@reduxjs/toolkit';
const selectPokemonById = memoize((id) => {
return createSelector(
(state) => state.pokemons,
(pokemons) => {
const pokemon = pokemons.find(id => p.id === id);
return pokemon;
}
)
})
createSelector
的问题是它只记住最后一个调用的参数(https://redux.js.org/usage/deriving-data-selectors#createselector-behavior)
为了克服这个问题,我们的想法是使用 lodash 的
createSelector
仅记住最近一组参数。那 意味着如果您使用不同的输入重复调用选择器,它 仍会返回结果,但必须不断重新运行 输出选择器产生结果:
memoize
函数来记忆给定参数的选择器。更多信息在这里:
https://dev.to/tilakmaddy_68/how-to-memoize- Correctly-using-redux-reselect-20m7
const parameterizedSelector = (state, someParam) => createSelector(
[otherSelector],
(otherSelectorResult) => someParam + otherSelectorResult
);
然后使用like
const mapStateToProps = state => ({
parameterizedSelectorResult: parameterizedSelector(state, 'hello')
});
虽然我不确定这种情况下的记忆/性能,但它确实有效。