Anyone knows how to delay time before it gives suggestions?
As soon as I write the first letter it gives me suggestions, I'd like to delay that, I read through the docs and couldn't find it, maybe it's not possible?
The conventional way is to use debounce
or throttle
to delay the function call while the user is typing. The delay behaviors are a bit different between them, see here for more info. For this answer I'll use debounce
from lodash
.
Also please do not copy the most upvoted answer. It is wrong and uses bad practice:
import debounce from 'lodash/debounce
debounce(handleSearch)
directly to the onUpdateInput
props. debounce
is a higher-order function, it is a function factory that creates another function that can be delayed:const handleSearch = () => { // ... }
const handleSearchDelayed = debounce(handleSearch, 50);
handleSearchDelayed();
handleSearchDelayed();
handleSearchDelayed();
// handleSearchDelayed is called 3 times but handleSearch will only be called 1 time
// 50ms later
This means that the debounce(handleSearch)
will create a new function with its own delay timer every time the component is re-render which is every time the user types in the textfield. This will create unexpected side-effects or even make the component not working at all.
The solution is to use useCallback
to return the same instance of the delay function when the component re-renders. Below is the minimal working example:
import React, { useCallback, useEffect, useState } from "react";
import Autocomplete from '@mui/lab/Autocomplete';
import TextField from '@mui/material/TextField';
import debounce from "lodash/debounce";
import { getOptionsAsync } from "./options";
function App() {
const [options, setOptions] = useState([]);
const [inputValue, setInputValue] = React.useState("");
const getOptionsDelayed = useCallback(
debounce((text, callback) => {
setOptions([]);
getOptionsAsync(text).then(callback);
}, 200),
[]
);
useEffect(() => {
getOptionsDelayed(inputValue, (filteredOptions) => {
setOptions(filteredOptions);
});
}, [inputValue, getOptionsDelayed]);
return (
<Autocomplete
options={options}
getOptionLabel={(option) => option.title}
filterOptions={(x) => x} // disable filtering on client
loading={options.length === 0}
onInputChange={(e, newInputValue) => setInputValue(newInputValue)}
renderInput={(params) => <TextField {...params} label="Combo box" />}
/>
);
}
You can use lodash's debounce() function (basically a little window.setTimeout trick to throttle repeated calls):
import _ from 'lodash';
...
doSearch(text) {
// Your normal handler here
}
...
// Delay autocomplete until 500 ms after use stops typing
<AutoComplete
onUpdateInput={_.debounce((value) => doSearch(value), 500)}
...
/>
There is example from my project with AutoComplete from Antd package:
const { AutoComplete } = antd
const WAIT_INTERVAL = 1000
let timerID
class Test extends React.Component {
handleSearch = (query) => {
clearTimeout(timerID)
timerID = setTimeout(() => {
console.log('some action after delay')
}, WAIT_INTERVAL)
}
render(){
return (
<AutoComplete
...
onSearch={handleSearch}
/>
)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With