1

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.

1
  • you can use reduce and combine the two operations (filtering and mapping) Commented Feb 12, 2021 at 22:07

1 Answer 1

1

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)
))}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.