Using multiple ID selectors
ghola opened this issue · comments
Hi there. I'm implementing a filter which gets applied to a list of items to be displayed in a table. The filter is basically a form which ends up building a criteria object. I store that object locally, inside the filter, since I see no point in making it globally available in redux (trying to maintain local state local). However, that criteria is used to filter data from the store, so it needs to get passed as a parameter to a selector. So I tried a couple of approaches, but none seems to work.
Using an object as the ID in createIdSelector
interface Criteria {
prop1: string;
prop2: boolean;
}
const getCriteria = createIdSelector((criteria: Criteria) => criteria);
// this throws a typing warning: Type 'Criteria' is not assignable to type 'string'
So the assumption here is the ID needs to be a string. I could try to serialize the criteria to a string, but then I would have to unserialize it back inside the selector to be able to use the data inside it. Is it the right way to do it or is it a hack?
Using multiple ID selectors
const getFilter1 = createIdSelector((prop1: string) => prop1);
const getFilter2 = createIdSelector((prop2: boolean) => prop2); // prop2 is boolean, but let's ignore it and assume it's a string
const getFiltered = createSelector(
[getSomeUnfiteredData, getFilter1 , getFilter2],
(data, filter1, filter2) => console.log(filter1, filter2)
);
getFiltered(state, 'filter1', 'filter2');
// will print: filter1 filter1
So there can be a single ID selector? The second ID selector gets completely ignored.
Hopefully the examples give you a good enough idea of what I'm trying to achieve. Can you guide me on how to do it?
I figured it out. It turns out I can use multiple ID selectors and a criteria object. It's the job of each selector to basically deconstruct the criteria object and offer it to the main selector.
interface Criteria {
prop1: string;
prop2: boolean;
}
const getProp1 = createIdSelector((criteria: Criteria) => criteria.prop1);
const getProp2 = createIdSelector((criteria: Criteria) => criteria.prop2);
const getFiltered = createSelector(
[getSomeUnfiteredData, getProp1 , getProp2 ],
(data, prop1, prop2) => console.log(prop1, prop2)
);
getFiltered(state, {prop1: 'filter1', prop2: 'filter2'});
// will print: filter1 filter2
From my testing this seems to memoize correctly for all variations of the criteria object.