Introduction:
AutoComplete input fields are a common user interface element used to help users efficiently find and select options from a predefined list. In this blog, we'll explore how to create a customizable AutoComplete input component in React with throttling to improve performance. We'll walk through the code for the component and explain its key features.
Creating the AutoCompleteInput Component:
The AutoCompleteInput
component is designed to provide a user-friendly AutoComplete experience. Let's break down its important components and functionality:
Props:
The component takes two props:options
andhandleSelection
. Theoptions
prop is an array of strings representing the available options, whilehandleSelection
is a callback function to handle the selected option.-
State and Refs:
-
inputRef
: This useRef hook is used to reference the input element for handling clicks outside the component. -
value
: Represents the current value of the input field. -
suggestions
: Stores the list of suggestions based on the user's input.
-
getSuggestions Function:
This function filters the available options based on the user's input. It converts both the input and options to lowercase for case-insensitive matching.onChange Function:
Whenever the input field's value changes, this function updates thevalue
state and recalculates the suggestions based on the new value.onSuggestionClick Function:
When a suggestion is clicked, this function sets the selected suggestion as the input value and calls thehandleSelection
callback with the selected value.isSuggestionEmpty Function:
This function checks if the suggestions list is empty or contains only an empty string. It is used to conditionally render the suggestions dropdown.Event Listener for Clicks Outside:
AnuseEffect
hook is used to add a click event listener to the document body. This listener detects clicks outside of the component, allowing it to blur and hide the suggestions dropdown.Throttling with Lodash:
To improve performance and responsiveness, we've added throttling to theonChange
event using thelodash/debounce
function. This reduces the frequency of function calls while the user is typing rapidly.
Installing Lodash:
Before implementing throttling, make sure to install the lodash
library using npm. Run the following command in your project directory:
npm install lodash
Rendering the Component:
The AutoCompleteInput
component is rendered within the Home
component. When the user selects a suggestion, the selected value is logged to the console.
Conclusion:
Creating an AutoComplete input component in React can enhance user experience when searching or selecting items from a list. The provided code demonstrates a basic implementation, and with the added throttling, it ensures smooth performance even with rapid typing.
Feel free to use this code as a starting point and adapt it to your specific needs. By following the installation instructions for lodash, you can easily add throttling to your React components. Happy coding!
"use client";
import AutoCompleteInput from "./components/AutoComplete";
const data = ["One", "Two", "Three"];
export default function Home() {
const handleSelection = (selectedOption: string) => {
console.log({ Selected: { selectedOption } });
};
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<AutoCompleteInput
options={data.map((v: string) => v)}
handleSelection={handleSelection}
/>
</main>
);
}
import React, { useEffect, useRef, useState } from "react";
import debounce from "lodash/debounce"; // npm install lodash
interface IPropType {
options: string[];
handleSelection: (val: string) => void;
}
const AutoCompleteInput = (props: IPropType) => {
const { options, handleSelection } = props;
const inputRef = useRef<HTMLInputElement>(null);
const [value, setValue] = useState("");
const [suggestions, setSuggestions] = useState([""]);
const getSuggestions = (inputValue: string) => {
if (typeof inputValue !== "string") {
return [];
}
const inputValueLowerCase = inputValue.toLowerCase();
return options.filter((option) =>
option.toLowerCase().includes(inputValueLowerCase),
);
};
// Debounce the onChange function
const debouncedOnChange = debounce((newValue: string) => {
setValue(newValue);
setSuggestions(getSuggestions(newValue));
}, 100); // Adjust the debounce delay as needed (e.g., 300 milliseconds)
const onSuggestionClick = (suggestion: string) => {
setValue(suggestion);
handleSelection(suggestion);
setSuggestions([]);
};
const isSuggestionEmpty = () => {
if (suggestions.length === 1 && suggestions[0] === "") {
return true;
} else return false;
};
// Add a click event listener to the document body to handle clicks outside of the component
useEffect(() => {
const handleDocumentClick = (e: any) => {
if (inputRef.current && !inputRef.current.contains(e.target)) {
inputRef.current.blur();
setSuggestions([]);
}
};
document.addEventListener("click", handleDocumentClick);
return () => {
document.removeEventListener("click", handleDocumentClick);
};
}, []);
return (
<div className="relative">
<input
ref={inputRef}
className="w-full border border-dark text-black transition-all duration-300 rounded-md px-4 py-3 focus:outline-none"
type="text"
placeholder="Search"
value={value}
onChange={(e) => debouncedOnChange(e.target.value)}
onFocus={() => {
setSuggestions(options);
setValue("");
}}
/>
{!isSuggestionEmpty() && suggestions.length > 0 && (
<ul
className="bg-white border-blue-500 border-2 rounded hover:cursor-pointer absolute top-14 w-full z-20 max-h-64 overflow-y-auto"
onPointerLeave={() => {
inputRef?.current?.blur();
setSuggestions([""]);
}}
>
{suggestions.map((suggestion) => (
<li
key={suggestion}
className="hover:bg-blue-500 hover:text-white transition duration-200 text-sm text-gray-700 p-1"
onClick={() => onSuggestionClick(suggestion)}
>
{suggestion}
</li>
))}
</ul>
)}
</div>
);
};
export default AutoCompleteInput;
Top comments (0)