How to Implement a Search Bar in React

Grace Yuiko Nakano
4 min readSep 14, 2021
Search Bar that filters through the seeded data from fetched API

Implement Search Bar seeded with data fetched from API

Having a search bar in your application is a feature that can heighten your application. I will walk through how to implement a search bar using:

  • Ant design search input
  • API endpoint to fetch the data
  • React hooks to build in functional component
  • functions to handle the filter in search
  • CSS to implement search bar dropdown and scroll
  1. Create SearchBar.js component
  2. Import and implement Ant design search input

Above is a link to explore different search input designs to implement in your application. I personally like this one and chose to implement the following. Ant design provides some boiler plate code to see the search input functioning on the frontend.

import {Input, Space, Button} from "antd";
const {Search} = Input;
const SearchBar = () => {const onSearch = value => console.log(value);return(
<div className="search">
<div className="searchInputs">
<Search
placeholder="input search text"
onSearch={onSearch}
enterButton
/>
}
export default SearchBar

3. useState Hooks

We can access state and set state within a functional component by utilizing useState hooks.

import {useState} from "react";
import {Input, Space, Button} from "antd";
const {Search} = Input;
const SearchBar = () => {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [error, setError] = useState("");
const onSearch = value => console.log(value);.
.
.
return(
<div className="search">
<div className="searchInputs">
<Search
placeholder="input search text"
onSearch={onSearch}
enterButton
/>
}
export default SearchBar

Make sure to set state for data and filteredData to an array so you can map through the array and retrieve each object.

4. useEffect hook to fetch data and return data

In order to retrieve the data from the API endpoint, we can utilize axios within our useEffect hook. Make sure to import axios to utilize.

import {useState, useEffect} from "react";
import axios from "axios";
import {Input, Space, Button} from "antd";
const {Search} = Input;
const SearchBar = () => {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [error, setError] = useState("");
useEffect(() => {
axios("http://localhost:3001/users")
.then((response) => {
console.log(response.data);
setData(response.data);
setFilteredData(response.data);
})
.catch((err) => {
console.log(err);
setError(err);
});
}, []);
.
.
.
const onSearch = value => console.log(value);return(
<div className="search">
<div className="searchInputs">
<Search
placeholder="input search text"
onSearch={onSearch}
enterButton
/>
}
export default SearchBar

Once the promise is resolved with a response, you want to take that response data and set it to the data and filtered data. You also want to implement catch to handle errors.

5. Implement functions to handle search filter

We no longer need our onSearch function and can replace it with a function that best matches the action and behavior — handleFilter

import {useState, useEffect} from "react";
import axios from "axios";
import {Input, Space, Button} from "antd";
const {Search} = Input;
const SearchBar = () => {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [error, setError] = useState("");
const [input, setInput] = useState("");
useEffect(() => {
axios("http://localhost:3001/users")
.then((response) => {
console.log(response.data);
setData(response.data);
setFilteredData(response.data);
})
.catch((err) => {
console.log(err);
setError(err);
});
}, []);
const handleFilter = (e) => {
console.log(e);
const searchInput = e.target.value;
setInput(searchInput);
const newFilter = data.filter((value) => {
return value.first_name.toLowerCase().includes(searchInput.toLowerCase());
});
if (searchInput === "") {
setFilteredData([]);
} else {
setFilteredData(newFilter);
}
};
return(
<div className="search">
<div className="searchInputs">
<Search
placeholder="input search text"
value={input}
onChange={(e) => handleFilter(e)}
enterButton
/>
</div>
{filteredData.length != 0 && (
<div className="dataResult">
{filteredData.slice(0, 10).map((value, index) => {
return (
<div className="dataItem" key={value.id}>
<p>{value.first_name} {value.last_name}</p>
</div>
);
})}
</div>
)}
</div>
)
}
export default SearchBar

We want to set that input to the target value of the event. The we want to filter through that data that we received and return the value name and call “toLowerCase()” so it is not case sensitive and will return the search letter regardless of whether it is lower or upper case. We want it to include the search input which is also not case sensitive. We sent a condition of the return.

In the JSX, we will call the onChange event listener inside the Search input to handle the event and callback. If the filteredData length is not 0, we want it to return the first 10 results and map through the array of the filtered data, returning the value.

You can implement some custom CSS to have a drop down for the search in a separate css file. The overflow-y allows for you to scroll up and down the y axis to view all the users.

.dataResult {
margin-top: 5px;
width: 300px;
height: 200px;
background-color: white;
box-shadow: rgba(0, 0, 0.35) 0px 5px 15px;
overflow: hidden;
overflow-y: auto;
}

--

--

Grace Yuiko Nakano

Fullstack Software Engineer | Musician | Food Lover | Coffee Addict