Reputation: 105
I have a list of events that i need to filter using three values (event name, event country and event City):
Here are the states for the inputs :
//set up search inputs (event name, event city, event country)
const [searchedEName, setSearchedEName] = useState("");
const [searchedECountry, setSearchedECountry] = useState("");
const [searchedECity, setSearchedECity] = useState("");
the inputs :
<div >
<input type="text" value={searchedEName} name="name" onChange={(e) => setSearchedEName(e.target.value)} />
<label>Event Name</label>
</div>
<div>
<input type="text" value={searchedECountry} name="country" onChange={(e) => setSearchedECountry(e.target.value)} />
<label>Country</label>
</div>
<div >
<input type="text" value={searchedECity} name="city"
onChange={(e) => setSearchedECity(e.target.value)} />
<label>City</label>
</div>
and finally the filtering and mapping of the array
<motion.div className="events" >
{availableEvents.filter((event) => {
if (searchedEName == "" && searchedECountry == "" && searchedECity == "") {
return event;
}
else if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && searchedECity == "" && searchedECountry == "") {
return event;
}
else if (event.event.country.toLowerCase().includes(searchedECountry.toLowerCase()) && searchedECity == "" && searchedEName == "") {
return event;
}
else if (event.event.city.toLowerCase().includes(searchedECity.toLowerCase()) && searchedEName == "" && searchedECountry == "") {
return event;
}
else if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && event.event.city.toLowerCase().includes(searchedECity.toLowerCase()) && searchedECountry == "") {
return event;
}
else if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && event.event.country.toLowerCase().includes(searchedECountry.toLowerCase()) && searchedECity == "") {
return event;
}
else if (event.event.city.toLowerCase().includes(searchedECity.toLowerCase()) && event.event.country.toLowerCase().includes(searchedECountry.toLowerCase()) && searchedEName == "") {
return event;
}
else if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && event.event.country.toLowerCase().includes(searchedECountry.toLowerCase()) && event.event.city.toLowerCase().includes(searchedECity.toLowerCase())) {
return event;
}
}).map((event) => {
return <Event key={event.event.id} event={event.event} />
})}
</motion.div>
Now this does work but i can't help but think that there should be a better way to do the filtering without coding every single possible scenario.
Please Can you help me find a solution to this.
Upvotes: 1
Views: 509
Reputation: 370769
Any string also contains the empty string. So, for example, assuming that event.event.eventName
will always exist as a string, this:
if (searchedEName == "" && searchedECountry == "" && searchedECity == "") {
return event;
} else if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && searchedECity == "" && searchedECountry == "") {
return event;
}
is equivalent to
if (event.event.eventName.toLowerCase().includes(searchedEName.toLowerCase()) && searchedECity == "" && searchedECountry == "") {
return event;
}
Continue this pattern, and you'll see that all of your branches are superfluous, except the one at the end - which can be made much more DRY with a helper function:
const contains = (event, prop, against) => event.event[prop].toLowerCase().includes(against.toLowerCase());
{availableEvents.filter(event => (
contains(event, 'eventName', searchedEName) &&
contains(event, 'country', searchedECountry) &&
contains(event, 'city', searchedECity)
))}
Upvotes: 1