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)