I have a search bar input:
<input
type="text"
className="px-4 py-2 w-80"
placeholder="Search"
onChange={(event) => searchWord(event.target.value)}
/>
I have this set up at the top of my file:
const [foundWords, setFoundWords] = useState<any>([]);
const [searchString, setSearchString] = useState('');
const fetchWords = async () => {
console.log("1", searchString);
axios.get(`http://localhost:8081/find?searchString=${searchString.toLowerCase()}`)
.then(({ data }) => setFoundWords(data));
}
const debounce = (fn: Function, ms = 300) => {
let timeoutId: ReturnType<typeof setTimeout>;
return function (this: any, ...args: any[]) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
const searchWord = debounce((input: string) => {
console.log("2", input)
setSearchString(input);
if (!input) return;
fetchWords()
}, 500);
The console log "1" above returns an empty string, but the console log "2" returns my search query.
What's going wrong with it?
You can use an useEffect
instead of directly calling the fetchWords
from the searchWord
function
I would update your code the following way
const [foundWords, setFoundWords] = useState<any>([]);
const [searchString, setSearchString] = useState('');
const fetchWords = useCallback((input: string) => {
axios.get(`http://localhost:8081/find?searchString=${input.toLowerCase()}`)
.then(({ data }) => setFoundWords(data));
}, [])
const debounce = (fn: Function, ms = 300) => {
let timeoutId: ReturnType<typeof setTimeout>;
return function (this: any, ...args: any[]) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
const searchWord = debounce((input: string) => {
setSearchString(input);
}, 500)
useEffect(() => {
if (searchString) {
fetchWords(searchString)
}
}, [searchString, fetchWords])
UseEffect would be guaranteed to trigger only after the searchString is updated. And as per useCallback
for fetchWords
. It is a better optimization and a good practice for functions used inside useEffect
to be wrapped inside useCallback
Also, you can further optimize your code in the following way if it is not required to trigger render cycle again on change of searchString
.
const [foundWords, setFoundWords] = useState<any>([]);
const fetchWords = useCallback((input: string) => {
axios.get(`http://localhost:8081/find?searchString=${input.toLowerCase()}`)
.then(({ data }) => setFoundWords(data));
}, [])
const debounce = (fn: Function, ms = 300) => {
let timeoutId: ReturnType<typeof setTimeout>;
return function (this: any, ...args: any[]) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
const searchWord = debounce((input: string) => {
if (input) {
fetchWords(input)
}
}, 500)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.