Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call combined reselect selector from redux-saga

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

like image 762
user1665355 Avatar asked Dec 08 '25 10:12

user1665355


2 Answers

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.

like image 120
Alex Avatar answered Dec 10 '25 00:12

Alex


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);
    },
  );```
like image 38
Kasia Avatar answered Dec 10 '25 00:12

Kasia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!