I am trying to call a combined selector from redux-saga. The idea is that I have two drop downs. Choices in first drop down will filter the appropriate values in second drop down, i.e. my combined selector will filter out some non relevant values, so they will not be shown in second drop down:
1) I have two selectors, firstSelector and secondSelector
// firstSelector returns {"Cat":["black","white"],"Dog":["grey"]}
const firstSelector= () =>
createSelector(selectPage, substate => substate.firstDropDown);
// secondSelector returns ["black","grey"]
const secondSelector= () =>
createSelector(selectPage, substate => substate.secondDropDown);
2) I combine those in combined selector (which should return ["black", "grey"], i.e. "white" is filtered out)
const filterBySelection = (firstSelector, secondSelector) =>
createSelector(
[
firstSelector,
secondSelector,
],
(first, second) => {
const filteredValues = Object.keys(first).reduce(
(r, k) => r.concat(first[k]),
[],
);
return second.filter(val => filteredValues.indexOf(val) >= 0);
},
);
3) But how can I call filterBySelection in redux-saga?
I tried:
const filteredValues = yield select(
filterBySelection,
firstSelector,
secondSelector,
);
And
const filteredValues = yield select(
filterBySelection(firstSelector, secondSelector)()
);
And
const filteredValues = yield select(
filterBySelection(firstSelector, secondSelector)
);
But those ways do not work.
Though, I can call firstSelector or secondSelector, i.e. works:
const firstData= yield select(firstSelector());
Someone can say that I can simply do the below in redux-saga:
const first = yield select(firstSelector());
const second = yield select(secondSelector());
const filtered = Object.keys(first).reduce(
(r, k) => r.concat(first[k]),
[],
);
const secondFiltered = second.filter(
val => first.indexOf(val) >= 0,
);
But that will not memoize and the idea is to memoize.
So is it possible to use a memoized selector in redux-saga?
Best Regards
You seems to miss call the function to return the selector. So, either:
a)
const filterBySelection = (firstSelector, secondSelector) =>
createSelector(
[
firstSelector(), // <- parentheses
secondSelector(), // <- parentheses
], ... )
then: const filteredValues = yield select(
filterBySelection(firstSelector, secondSelector)
);
b) pass selectors correctly
const filteredValues = yield select(
filterBySelection(firstSelector(), secondSelector())
);
c) define firstSelector and secondSelector without function (perhaps the most true way):
const firstSelector =
createSelector(selectPage, substate => substate.firstDropDown);
const secondSelector =
createSelector(selectPage, substate => substate.secondDropDown);
then
const filteredValues = yield select(
filterBySelection(firstSelector, secondSelector)
);
Hope it helps.
I would go with something like this
createSelector(
firstSelector,
secondSelector,
(first, second) => {
const filteredValues = Object.keys(first).reduce(
(r, k) => r.concat(first[k]),
[],
);
return second.filter(val => filteredValues.indexOf(val) >= 0);
},
);```
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With