josepot / redux-views

Like Reselect but with better support for shared-selectors

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.