React Live Search

React Live Search cover image

Category: WebDev

Posted at: Jun 9, 2024

9 Minutes Read

Method 1. filter()

This method is for rendered items. For example, you got all the users from an API request and store them in a variable and you want to filter them using specific keywords from keys like name or email.


const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");

users: State variable that holds the list of users.

setUsers: Function used to update the users state variable.

search: State variable that holds the search term input by the user.

setSearch: Function used to update the search state variable.


Then, we will use Axios to fetch user data from an API, but you have to install it first:

npm install axios


useEffect ensures that the data is fetched from the API when the component is rendered

useEffect(() => {
 try {
   axios
     .get(
       "https://randomuser.me/api/?exc=login,registered,location,cell,id,nat,gender&results=1000"
     )
     .then((res) => {
       setUsers(res.data.results);
     })
     .catch((err) => {
       console.log(err);
     });
 } catch (err) {
   console.log(err);
 }
}, []);

here I used randomuser to generate random users


Search input:

<input
  type="text"
  className="search__input"
  placeholder="Search..."
  value={search}
  onChange={(event) => setSearch(event.target.value)}
/>


Mapping and Filtering results:

<div className="results">
  {users
    .filter(
      (user) =>
        new RegExp(`${search.toLowerCase()}.*`).test(
          user.name.first.toLowerCase()
        ) ||
        new RegExp(`${search.toLowerCase()}.*`).test(
          user.name.last.toLowerCase()
        )
    )
    .map((user, i) => {
      return (
        <Card
          first={user.name.first}
          last={user.name.last}
          email={user.email}
          img={user.picture.thumbnail}
        />
      );
    })}
</div>

In the filter method, I used Regex to search for the provided key word and converting them to lowercase. Here is another method without Regex:

.filter((user) => {
  const searchTerm = search.toLowerCase();
  return (
    user.name.first.toLowerCase().includes(searchTerm) ||
    user.name.last.toLowerCase().includes(searchTerm) ||
    user.email.toLowerCase().includes(searchTerm)
  );
})


Final code:

import React, { useState, useEffect } from "react";
import axios from "axios";
import Card from "./Card";

function App() {
  const [users, setUsers] = useState([]);
  const [search, setSearch] = useState("");

  useEffect(() => {
    try {
      axios
        .get(
          "https://randomuser.me/api/?exc=login,registered,location,cell,id,nat,gender&results=1000"
        )
        .then((res) => {
          setUsers(res.data.results);
        })
        .catch((err) => {
          console.log(err);
        });
    } catch (err) {
      console.log(err);
    }
  }, []);


  return (
    <div className="container">
      <input
        type="text"
        className="search__input"
        placeholder="Search..."
        value={search}
        onChange={(event) => setSearch(event.target.value)}
      />
      <p className="text">Search Results for "{search}"</p>
      <div className="results">
        {users
          .filter(
            (user) =>
              new RegExp(`${search.toLowerCase()}.*`).test(
                user.name.first.toLowerCase()
              ) ||
              new RegExp(`${search.toLowerCase()}.*`).test(
                user.name.last.toLowerCase()
              )
          )
          .map((user, i) => {
            return (
              <Card
                first={user.name.first}
                last={user.name.last}
                email={user.email}
                img={user.picture.thumbnail}
              />
            );
          })}
      </div>
    </div>
  );
}


export default App;

Method 2. API Call on each change

This method is useful when you have an API that handles the search process in the back-end, and you only need to provide the search term.


We will have to change the useEffect method by putting the search variable in the URL and between the brackets [] to initiate the request whenever search changes

useEffect(() => {
 try {
   axios
     .get(
       `https://api.example.com/users/search/${search}`
     )
     .then((res) => {
       setUsers(res.data.results);
     })
     .catch((err) => {
       console.log(err);
     });
 } catch (err) {
   console.log(err);
 }
}, [search]); // to initiate the request whenever the variable changes

Each API have it own method, some API's use POST request but in this method the search term will be as a route


Finally mapping the results:

<div className="results">
  {users.map((user, i) => {
      return (
        <Card
          first={user.name.first}
          last={user.name.last}
          email={user.email}
          img={user.picture.thumbnail}
        />
      );
    })}
</div>


Final code:

import React, { useState, useEffect } from "react";
import axios from "axios";
import Card from "./Card";

function App() {
  const [users, setUsers] = useState([]);
  const [search, setSearch] = useState("");

  useEffect(() => {
    try {
      axios
        .get(
          `https://api.example.com/users/search/${search}`
        )
        .then((res) => {
          setUsers(res.data.results);
        })
        .catch((err) => {
          console.log(err);
        });
    } catch (err) {
      console.log(err);
    }
  }, [search]);


  return (
    <div className="container">
      <input
        type="text"
        className="search__input"
        placeholder="Search..."
        value={search}
        onChange={(event) => setSearch(event.target.value)}
      />
      <p className="text">Search Results for "{search}"</p>
      <div className="results">
        {users.map((user, i) => {
            return (
              <Card
                first={user.name.first}
                last={user.name.last}
                email={user.email}
                img={user.picture.thumbnail}
              />
            );
          })}
      </div>
    </div>
  );
}


export default App;