I have an input field in React, in this input field the user is typing a message. I want, when the user starts typing, to call a function only once. I tried a solution, but it's calling the function again and again.
export default function App() {
let typingTimer; //timer identifier
let doneTypingInterval = 5000;
let myInput = document.getElementById("input-text");
//on keyup, start the countdown
if (myInput) {
myInput.addEventListener("keyup", () => {
clearTimeout(typingTimer);
if (myInput.value) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
}
//user is "finished typing," do something
function doneTyping() {
console.log("done");
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<form>
<input type="search" id="input-text" placeholder="Start typing...." />
</form>
</div>
);
}
The above code is calling doneTyping after 5 seconds, but five times. I want to call only once, and same when the user stops typing.
i am pretty sure its a closure issue. this code example works just fine for reset the timer.
HTML:
<input type="button" id="test">
JS:
let timer;
document.getElementById('test').addEventListener('click', () => {
clearTimeout(timer);
timer = setTimeout(callback, 1000);
})
function callback() {
console.log('called');
}
You want to use something like Debounce.
Here's a working example based on your code at Codesandbox.
Note: Do check the console.
import React, { useRef } from "react";
const DEBOUNCE_THRESHOLD = 500;
export default function App() {
const timeoutHandler = useRef(null);
const handleChange = (event) => {
if (timeoutHandler.current) {
clearTimeout(timeoutHandler.current);
}
timeoutHandler.current = setTimeout(() => {
console.log(event.target.value);
}, DEBOUNCE_THRESHOLD);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<form>
<input
type="search"
onChange={handleChange}
id="input-text"
placeholder="Start typing...."
/>
</form>
</div>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>