I'm trying to search for a product from my database and using lodash's debounce
to send request after a certain time. The problem I'm facing is that the request is going after the specified time only but requests are fired for each character after the time interval specified. I want only one request to be triggered and that to for the entire word, not for each letter. What am i doing wrong here ? Also, I'm open to any optimization in this code if any :)
SearchBar.js
function SearchBar() {
const [searchText, setSearchText] = useState("");
const searchResultsRef = useRef(null);
const dispatch = useDispatch()
const sendRequest = (searchText) => {
dispatch(getSearchedCategories(searchText))
};
const debouncedSendRequest = debounce(sendRequest, 5000);
const handleInputChange = (event) => {
const inputValue = event.target.value.toLowerCase();
if (inputValue === "") {
setSearchText("");
} else {
setSearchText(inputValue);
if(inputValue.trim().length > 2) {
debouncedSendRequest(inputValue.trim())
setShowSearchResult(true)
}
}
};
const hideSearchResults = () => {
setShowSearchResult(false);
}
useEffect(() => {
const handleClickOutside = (event) => {
if (searchResultsRef.current && !searchResultsRef.current.contains(event.target)) {
hideSearchResults();
}
};
// add event listener to detect clicks outside of the search component
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [searchResultsRef]);
return (
<div className="searchContainer">
<div className="searchInputs">
<input
type="search"
placeholder="Search for a product"
value={searchText}
onChange={handleInputChange}
/>
...
</div>
...
</div>
);
}
action.js
export const getSearchItem = (searchedItem) => async (dispatch) => {
try {
...
const { data } = axios.get(// my api)
...
} catch(error) {
...
}
}
const debouncedSendRequest = debounce(sendRequest, 5000);
Every time the component renders, this line creates a brand new debouncedSendRequest
function. It has its own internal timer not related to the last time you created it. For the debouncing to work you must create the function just once. You can do this with useMemo
:
const debouncedSendRequest = useMemo(() => {
const sendRequest = (searchText) => {
dispatch(getSearchedCategories(searchText))
};
return debounce(sendRequest, 5000);
}, [dispatch]);