Geethika
Geethika2y ago

Set.prototype.has() returns false even when element is present

I learning React.js, and would like to implement filter functionality based on the checkboxes selected. I am referring to this solution >> https://codepen.io/trezy/pen/GROLXqo So far, I have the following implementation: Code for filter function:
const [state, setState] = useState({ products: cspaces, filters: new Set(), })
const handleFilterChange = useCallback(event => { setState(previousState => { let filters = new Set(previousState.filters) let products = cspaces ..... products = products.filter(product => { return filters.has( product.attributes.propertySubType.split(" ").forEach(element => { if((element.match(/Shop|Office|Showroom/))!=null) console.log("element ", element) return element .... console.log("products ",products) } return { filters, products, } }) }, [setState]) The checkboxes: ... {data.propertytype.items.map((tag, index) => ( <li key={tag.value}> <Form.Check type="checkbox" value={tag.label} onChange={handleFilterChange} /> </li> ... And my component using the filtered data, ... {state.products.map((filteredListItems, id) => ( <Col key={id} sm="6" lg="4" className="mb-5 hover-animate" > <CardCspace data={filteredListItems} /> </Col> ))} ... cspaces is holding the data fetched from API. The value of state.products returned by filtering function is always empty. I would like to match with the categories "Shop", "Office", or "Showroom" which are displayed in checkboxes. Sample console output:
Solution:
filters.some(filter => product.attributes.propertySubType.split(" ").includes(filter))
filters.some(filter => product.attributes.propertySubType.split(" ").includes(filter))
Jump to solution
22 Replies
ghardin137
ghardin1372y ago
forEach returns nothing. so that would make sense so you're basically doing set.has(undefined)
Geethika
GeethikaOP2y ago
Thank you for your reply @ghardin137 . I have edited my code and am using .filter() in place of forEach(), does this help? How should I proceed?
ghardin137
ghardin1372y ago
what are the values in the set/ because filter will return an array and it'll be a new reference so i'm guessing that's probably not what you want
Geethika
GeethikaOP2y ago
As u can see in the sample console output I posted, I have chosen "Shop, it can also have multiple values
ghardin137
ghardin1372y ago
so the set contains strings and you want to only get the products that have one of the values in the set in propertySubType? or all of the values in the set/
Geethika
GeethikaOP2y ago
I would like to return the products which have the filters set values in ...propertySubType, which is a string. Hence I have split it on space
ghardin137
ghardin1372y ago
you don't necessarily have to split it you want it to have one of the values in filters or ALL of the values in filters?
Geethika
GeethikaOP2y ago
All the values
ghardin137
ghardin1372y ago
like is filters an AND or an OR any reason you're using a set over an array here?
Geethika
GeethikaOP2y ago
Well, I am using already-implemented solutions in my code
ghardin137
ghardin1372y ago
not sure what that means exactly. this would be simpler if filters was an array instead of a set
Geethika
GeethikaOP2y ago
In that case, I will use an array and check if that helps. Thank you
ghardin137
ghardin1372y ago
i mean it won't solve your problem you'd need a combination of array.prototype.every and array.prototype.includes here and change your logic if it were an array you could do like
filters.every(filter => product.attributes.propertySubType.split(" ").includes(filter))
filters.every(filter => product.attributes.propertySubType.split(" ").includes(filter))
and that would tell you if all of the filters are in the propertySubType
Geethika
GeethikaOP2y ago
I will try to implement this. Could you please tell me how to properly add and remove items from the filters array? if (event.target.checked) { filters.push(event.target.value) } else { var index = filters.indexOf(event.target.value) filters.splice(index, 1) } Im doing this
ghardin137
ghardin1372y ago
i would use filter rather than splice you generally want your updates to be immutable so you'd do like
filters = [...filters, event.target.value]
filters = [...filters, event.target.value]
and
filters = filters.filter(value => value !== event.target.value)
filters = filters.filter(value => value !== event.target.value)
Geethika
GeethikaOP2y ago
Though I am using every on filters, if i select multiple filters the products array is empty
ghardin137
ghardin1372y ago
do you have any products that have both of those filters? a product that's both Shop and Showroom?
Geethika
GeethikaOP2y ago
No not both of them at once, but separately..like I would like sites that are showrooms and sites that are shops to be displayed.
ghardin137
ghardin1372y ago
so it's an or not an and
Geethika
GeethikaOP2y ago
Yeah that would be correct
Solution
ghardin137
ghardin1372y ago
filters.some(filter => product.attributes.propertySubType.split(" ").includes(filter))
filters.some(filter => product.attributes.propertySubType.split(" ").includes(filter))
Geethika
GeethikaOP2y ago
Thanks a ton! It works