How do I pass additional parameters to combined selectors? I am trying to
• Get data
• Filter data
• Add custom value to my data set / group data by 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)
returns undefined
Updated: 4 December 2023
No changes compared to 4.1, but the updated document of version 5.0.0 using Typescript. Read document for more detail about the exceptional case.
// 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));
Updated: 16 February 2022
New Solution from Reselect 4.1: See detail
// 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'));
Updated: 6 March 2021
Solution from Reselect: See detail
// 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)
Old:
This is my approach. Creating a function with parameters and return function of reselect
.
export const selectWithValue = (CUSTOM_PARAMETER) => createSelector(
selectAllDataFiltered,
(data) => {
console.log(CUSTOM_PARAMETER)
return data[CUSTOM_PARAMETER]
}
)
const data = selectWithValue('myValue')(myState);