Why My Debounce Functionality Is Not Working In A React App With Hooks?
My goal is to fire a fetch request to get data from an API after some delay. In my particular case, I have an input field where a user can input a post ID. I don't want fire a fetc
Solution 1:
The main issue here is that you are calling the function only when input != "".
Till then input is not set to the desired value and thus the function becomes a no-op.
This change will however help
import { useCallback, useEffect, useState } from'react'import'./App.css'functiondebounce(fn, ms) {
let timeoutId
returnfunction (...args) {
if (timeoutId) clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
fn(...args)
}, ms)
}
}
exportdefaultfunctionApp() {
const [input, setInput] = useState('')
consthandleInputChange = (e) => {
setInput(e.target.value);
debouncedFireRequest(e.target.value);
};
const debouncedFireRequest = useCallback(
debounce(async (value) => {
if (value !== '') {
let res = awaitfetch(`https://jsonplaceholder.typicode.com/posts/${value}`)
let resData = await res.json()
console.log(resData)
}
}, 1000),
[]
);
return (
<divclassName='App'><inputtype='text'onChange={handleInputChange}value={input}></input></div>
);
}Solution 2:
Try this:
useEffect(() => {
const apiCallTimeoutId = setTimeout(() => {
fireRequest()
}, 1000);
return() =>clearTimeout(apiCallTimeoutId);
}, [input]);
1 sec after the user stops typing the request will be fired.
Solution 3:
This answer is on the right track but there's no need to keep const fireRequest = useCallback(debounce(fetchData, 1000), []) as it seems to imply.
Just fire the timeout, then clear it in the useEffect cleanup callback if the component rerenders:
<scripttype="text/babel"defer>const {useState, useEffect} = React;
constExample = () => {
const [input, setInput] = useState("");
const [result, setResult] = useState();
const fetchData = async () => {
if (input) {
try {
const res = awaitfetch(`https://jsonplaceholder.typicode.com/posts/${input}`);
if (res.ok) {
setResult(await res.json());
}
}
catch (err) {
console.error(err);
}
}
}
useEffect(() => {
const timeout = setTimeout(fetchData, 1000);
return() =>clearTimeout(timeout);
}, [input]);
return (
<div><inputplaceholder="type a small number, e.g. 12"onChange={e => setInput(e.target.value)}
value={input}
/>
{result && <div>{result.title}</div>}
</div>
);
};
ReactDOM.render(<Example />, document.body);
</script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>Note the try-catch on the fetch call and checking res.ok rather than throwing when res.json() fails.
Post a Comment for "Why My Debounce Functionality Is Not Working In A React App With Hooks?"