Implementing a Real-time Search Filter (on an array of objects) in React

Implementing a Real-time Search Filter (on an array of objects) in React

ยท

3 min read

Recently, I had a technical challenge for an interview and one of the tasks was to add a search feature to a contact list app.

You can see how it works here: https://kn8a.github.io/phonebook-react/ (Please don't delete entries there, and if you do, add one instead of the one you deleted ๐Ÿ˜‰) and here's the repo if you want to see the code: https://github.com/kn8a/phonebook-react

How to implement a simple search in your app;

For this example we have an array of objects that looks like this:

// Array example
const contacts = [
    { 
      id: 1111, 
      name: 'John Smith', 
      phone: '111-222-333', 
      email: 'john@smith.com' 
    },
    { 
      id: 1112, 
      name: 'Sarah Connor', 
      phone: '123-456-7890', 
      email: 'sarah@connor.net' 
    }
]

First, let's start with creating the state variables we need. We need a state variable to hold the value of the text input field, and another state variable to hold the filtered contacts.

const [searchValue, setSearchValue] = useState(""); // Initialize the searchValue state variable as an empty string
const [filteredContacts, setFilteredContacts] = useState(contacts); // Initialize the filteredContacts state variable with the contacts array

Next, we need to create a function that updates the searchValue state variable with the value of the text input field, and filters the contacts array based on the search value.

const handleSearch = e => {
  setSearchValue(e.target.value); // Update searchValue state with current text input value
  if (searchValue) { 
    const filteredData = contacts.filter(item => {
    // Convert all values of the contact object to a string, join     them, convert the string to lowercase and return the contact object if it includes the searchValue
      return Object.values(item)
        .join('')
        .toLowerCase()
        .includes(searchValue.toLowerCase());
    });
    setFilteredContacts(filteredData); // Update filteredContacts state with filtered array
  } else {
    setFilteredContacts(contacts); // Reset filteredContacts to all contacts when input is empty
  }
};

This function updates the searchValue state variable with the current value of the text input field, filters the contacts array based on the search value, and updates the filteredContacts state variable with the filtered contacts. If searchValue is an empty string, it will reset the filteredContacts to the initial contacts array.

Finally, in the JSX, we add a text input field and pass the handleSearch function as the onChange prop, and value of searchValue as the value prop. And we render the filteredContacts array using the map() function.

return (
  <div>
    <input type="text" onChange={handleSearch} value={searchValue} placeholder="Search contacts" />
    {filteredContacts.map(contact => (
      <div key={contact.id}>
        <p>Name: {contact.name}</p>
        <p>Phone: {contact.phone}</p>
        <p>Email: {contact.email}</p>
      </div>
    ))}
  </div>
);

And that's it! With just a few lines of code, you now have a search feature that filters displayed contacts as the user types. Note that when the input is empty, all the contacts will be displayed and when there is something in the input field, only the contacts that match the search will be displayed. In my app, I used a ternary expression to display filteredContacts if searchInput.length > 0, else display contacts. But I believe the approach I described here is more 'elegant'.

I hope you found this helpful and that it makes adding a search feature to your React app a little less daunting. Happy coding!

ย