Reputation: 454
i have the the following array of object which indicated all the possible combination of a product
[{id:25,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Medium"},{id: 0, name: "Packaging", option: "Card"}
{id:26,attributes:[{id: 0, name: "Weight", option: "500gr"},{id: 0, name: "Roast", option: "Medium"},{id: 0, name: "Packaging", option: "Card"}
{id:27,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Light"},{id: 0, name: "Packaging", option: "Card"}
{id:28,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Light"},{id: 0, name: "Packaging", option: "Tin"}
]
On the webpage, options are set via select; the select also set a state component as follow:
{Weight:"",Roast:"",Pakaging:""}
with the values from the selected option, for example (assuming only weight and roast are selected):
{Weight:"250gr",Roast:"Light",Packaging:""}
everytime a option is selected i want to narrow down the combination of product (based on the selection) until i finally got only one option available (also the combination are used for dinamically repopulate select, adding or removing available options based on previous selections)
until now i was using something like (inside the function called by onChange on a select):
const result = variations.filter((p) =>
p.attributes.some((c) => c.option === event.target.value)
);
but this way it reduces based on the latest selection, so if i start selecting 250gr it gives me a set of 3 (25,27,28) then if i select Medium, it give me a set of 2 (25 and 26) filtering only on medium and ignoring Weight
i'm looking to convert my filter, instead that on event.target.value, on the object but i cant find the right method, anyone can help?
Upvotes: 0
Views: 518
Reputation: 8774
You need to persist the selected filters like this:
const [filters, setFitlers] = React.useState({});
const onFilterChange = (e) => {
setFitlers(prevFilters => ({...prevFilters, [e.target.name]: e.target.name})
}
Now you can filter like this:
const result = variations.filter((p) =>
Object.entries(filters).every(([key, value]) => p.attributes[key] === value)
);
Obejct.entries will give you the key and value pairs of the filter object. And with every, you check if all the filters match.
Now you only have to give the input a name to fit your name:
<input name="weight" onChange={onFilterChange} .../>
To remove filters, maybe filter the filter object as well to remove empty strings:
Object.entries(filters).filter(([key,value) => value).every....
Upvotes: 1