Multi Select Search Using ReactJS
Last Updated :
25 Jul, 2024
Multi-Select Search Using ReactJS enables users to search for and select multiple items from a list simultaneously, enhancing usability and efficiency in interfaces like forms or tag selection. React interviews often include challenges related to building interactive and user-friendly components. One such common task is creating a multi-select search functionality. This article will guide you through a practical example of implementing a multi-select search component using React.
Prerequisites:
Approach to implement Multi Select Search:
The goal is to create a multi-select search component where users can type a query, see suggestions, and select multiple options. The selected options will be displayed as pills, and users can remove them individually.
Steps to Create the Project:
- Step 1: Set Up Your React App with Vite:
npm create vite@latest
- Step 2: Navigate to the Project Directory
cd multi-select-search
- Step 3: Install the package dependency.
npm install
Project Structure:
project structureThe updated dependencies in package.json file will look like:
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"web-vitals": "^2.1.4"
}
CSS
/* App.css */
body {
font-family: sans-serif;
}
.user-search-container {
display: flex;
position: relative;
}
.user-search-input {
width: 100%;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
padding: 5px;
border: 1px solid #ccc;
border-radius: 20px;
}
.user-search-input input {
border: none;
height: 20px;
padding: 5px;
}
.user-search-input input:focus {
outline: none;
}
.suggestions-list {
max-height: 300px;
overflow-y: scroll;
list-style: none;
padding: 0;
margin: 0;
position: absolute;
background-color: #fff;
border: 1px solid #ccc;
}
.suggestions-list li {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 10px;
cursor: pointer;
border-bottom: 1px solid #ccc;
}
.suggestions-list li:last-child {
border-bottom: none;
}
.suggestions-list li:hover {
background-color: #ccc;
}
.suggestions-list li img {
height: 20px;
}
.user-pill {
height: 20px;
display: flex;
align-items: center;
gap: 5px;
background-color: black;
color: #fff;
padding: 5px 10px;
border-radius: 16px;
cursor: pointer;
}
.user-pill img {
height: 100%;
}
.suggestions-list li.active {
background-color: #ccc;
}
JavaScript
// App.jsx
import { useEffect, useRef, useState } from "react";
import "./App.css";
import Pill from "./components/Pill";
function App() {
const [searchTerm, setSearchTerm] = useState("");
const [suggestions, setSuggestions] = useState([]);
const [selectedUsers, setSelectedUsers] = useState([]);
const [selectedUserSet, setSelectedUserSet] = useState(new Set());
const [activeSuggestion, setActiveSuggestion] = useState(0);
const inputRef = useRef(null);
useEffect(() => {
const fetchUsers = () => {
setActiveSuggestion(0);
if (searchTerm.trim() === "") {
setSuggestions([]);
return;
}
fetch(`https://dummyjson.com/users/search?q=${searchTerm}`)
.then((res) => res.json())
.then((data) => setSuggestions(data))
.catch((err) => {
console.error(err);
});
};
fetchUsers();
}, [searchTerm]);
const handleSelectUser = (user) => {
setSelectedUsers([...selectedUsers, user]);
setSelectedUserSet(new Set([...selectedUserSet, user.email]));
setSearchTerm("");
setSuggestions([]);
inputRef.current.focus();
};
const handleRemoveUser = (user) => {
const updatedUsers = selectedUsers.filter(
(selectedUser) => selectedUser.id !== user.id
);
setSelectedUsers(updatedUsers);
const updatedEmails = new Set(selectedUserSet);
updatedEmails.delete(user.email);
setSelectedUserSet(updatedEmails);
};
const handleKeyDown = (e) => {
if (
e.key === "Backspace" &&
e.target.value === "" &&
selectedUsers.length > 0
) {
const lastUser = selectedUsers[selectedUsers.length - 1];
handleRemoveUser(lastUser);
setSuggestions([]);
} else if (e.key === "ArrowDown" &&
suggestions?.users?.length > 0) {
e.preventDefault();
setActiveSuggestion((prevIndex) =>
prevIndex < suggestions.users.length - 1 ?
prevIndex + 1 : prevIndex
);
} else if (e.key === "ArrowUp" &&
suggestions?.users?.length > 0) {
e.preventDefault();
setActiveSuggestion((prevIndex) =>
(prevIndex > 0 ? prevIndex - 1 : 0));
} else if (
e.key === "Enter" &&
activeSuggestion >= 0 &&
activeSuggestion < suggestions.users.length
) {
handleSelectUser(suggestions.users[activeSuggestion]);
}
};
return (
<div className="user-search-container">
<div className="user-search-input">
{/* Pills */}
{selectedUsers.map((user) => {
return (
<Pill
key={user.email}
image={user.image}
text={`${user.firstName} ${user.lastName}`}
onClick={() => handleRemoveUser(user)}
/>
);
})}
{/* input feild with search suggestions */}
<div>
<input
ref={inputRef}
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search For a User..."
onKeyDown={handleKeyDown}
/>
{/* Search Suggestions */}
{searchTerm && (
<ul className="suggestions-list">
{suggestions?.users?.map((user, index) => {
return !selectedUserSet.has(user.email) ? (
<li
className={index === activeSuggestion ?
"active" : ""}
key={user.email}
onClick={() => handleSelectUser(user)}
>
<img
src={user.image}
alt={`${user.firstName}
${user.lastName}`}
/>
<span>
{user.firstName} {user.lastName}
</span>
</li>
) : (
<></>
);
})}
</ul>
)}
</div>
</div>
</div>
);
}
export default App;
JavaScript
// main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
JavaScript
// Pill.jsx
const Pill = ({ image, text, onClick }) => {
return (
<span className="user-pill" onClick={onClick}>
<img src={image} alt={text} />
<span>{text} ×</span>
</span>
);
};
export default Pill;
Steps to run the application:
npm run dev
Output:
Similar Reads
ReactJS Semantic UI Search Module Semantic UI is a modern framework used in developing seamless designs for the website. It gives the user a lightweight experience with its components. It uses predefined CSS and JQuery to incorporate them into different frameworks. In this article, we will learn how to use the Search Module in React
2 min read
Recipe Finder using ReactJS In this project article, we will be creating a recipe finder application using the React library. We have given the application the name "GeeksforGeeks Recipe Finder". This application is completely developed in ReactJS and mainly focuses on the functional components and also manages the various sta
5 min read
Movie Trailer app using ReactJS In this article, we are going to make a simple app that searches for any movie/web series trailers. The users can search for their favourite movie trailers using this application. The API will fetch the trailer from the internet and display it on the webpage. We will use 'movie-trailer' npm package
3 min read
ReactJS useSelect hook The useSelect is a custom hook provided by the Rooks package for React. It is a list selection hook that helps select values from a list. Arguments: list: It is of the type array which describes the list of items for the selection. The default value is undefined.initialIndex -It is of the type numbe
2 min read
How to Build a Search Filter using React Hooks ? In modern web development, implementing a search feature is a common requirement for various applications. With React Hooks, developers can efficiently manage state and lifecycle events, making it an ideal choice for building interactive user interfaces, including search functionalities. In this art
4 min read
How to Use react-select in React Application? React Select is a flexible and handy dropdown library for React that handles multi-select, loading data asynchronously, custom options, and more in your components with ease. In this article, we will see how to use react-select in React Application. PrerequisiteNode.js installednpm or yarn package m
2 min read