interesting_coderoom
interesting_coderoom

Reputation: 41

How to handle multiple select dropdowns in a React application with a single function?

I have a forms with 3 select dropdowns that filter an array based on a selected value. Rather than having an onChange handler for each of these forms I was wondering if I could use a single function too handle all of them based on a parameter.

I tried passing a string into the function but it doesn't work since it is expecting an event to be passed as a parameter.

Here is the code for the react form:

const UserSearchBox = ({ handleChange, handleLocationChange, handleTeamChange, handleClientChange }) => {
    return (
        <form className="user-search">
            <input className="user-input" placeholder="Search for Peeps" name="userSearch" onChange={handleChange} />

            <div>
                <select defaultValue="all" onChange={handleLocationChange}>
                    <option value="all">All</option>
                    <option value="boston">Boston</option>
                    <option value="chicago">Chicago</option>
                    <option value="tampa">Tampa</option>
                </select>

                <select defaultValue="all" onChange={handleTeamChange}>
                    <option value="all">All</option>
                    <option value="design">Design</option>
                    <option value="engineering">Engineering</option>
                    <option value="finance">Finance</option>
                </select>

                <select defaultValue="all" onChange={handleClientChange}>
                    <option value="all">All</option>
                    <option value="company">Company1</option>
                    <option value="company2">Company2</option>
                    <option value="company3">Company3</option>
                </select>
            </div>


        </form>
    )
}

And this is the code for the App:

const handleInputChange = (e) => {
    e.preventDefault();
    let searchTerm = e.target.value;

    if(searchTerm){
      let filteredUsers = users.filter((x) => x.name.toLowerCase().includes(searchTerm.toLowerCase()))
      setUsers(filteredUsers)
    } else{
      setUsers(allUsers)
    }
  }

  const handleLocationChange = (e) => {
    e.preventDefault();
    let searchTerm = e.target.value;

    if(searchTerm !== "all"){
      let filteredUsers = allUsers.filter((x) => x.location.toLowerCase().includes(searchTerm.toLowerCase()))
      setUsers(filteredUsers)
    } else{
      setUsers(allUsers)
    }
  }

  return (
    <div className="container-fluid">
      <Header name={loggedInUser.name} profile_photo={loggedInUser.profile_photo} />
      <UserSearchBox handleLocationChange={handleLocationChange} handleChange={handleInputChange}/>
      <Users users={users} />
    </div>
  )

Upvotes: 0

Views: 578

Answers (2)

interesting_coderoom
interesting_coderoom

Reputation: 41

Another potential solution, however I believe @Darkbound had a more precise method.

Add data attributes to the options:

<select defaultValue="all" onChange={handleSelectChange}>
                    <option data-filter-type="location" value="all">All</option>
                    <option data-filter-type="location" value="boston">Boston</option>
                    <option data-filter-type="location" value="chicago">Chicago</option>
                    <option data-filter-type="location" value="tampa">Tampa</option>
                </select>

Then use a switch statement:

if (searchTerm !== "all") {
      switch (attr) {
        case 'location':
          setUsers(users.filter((x) => x.location.toLowerCase().includes(searchTerm.toLowerCase())));
          break;
        case 'team':
          console.log('term: ', searchTerm);
          
          setUsers(users.filter((x) => x.team.toLowerCase().includes(searchTerm.toLowerCase())));
          break;
        case 'client':
          setUsers(users.filter((x) => x.client.toLowerCase().includes(searchTerm.toLowerCase())));
          break;
        default:
          setUsers(allUsers)
      }
    } else {
      setUsers(allUsers)
    }

Upvotes: 0

Darkbound
Darkbound

Reputation: 3434

You can pass additional parameters with the event by changing the onChange to this:

onChange={(e) => { handleLocationChange(e, param1, param2, param3...) }}

Or if you dont need the event you can skip it:

onChange{() => { handleLocationChange(param1, param2, param3...) }}

That way you still get your event inside, and then you add whatever other arguments you want.

Would that help you?

Upvotes: 1

Related Questions