Hi i have this component in React
,the purpose of this component when the input field value changes i am storing that value in messageIput state variable
,and when the user starts typing i m calling handleMessagePress
and printing composing
and wait for five seconds if user still types after five i m again printing composing
and if user stop typing then i m calling handleChange
and prints paused
. But Now the problem is when i m setting the value in messageIput state variable
at that time its printing composing again again . I want How the below snippet is working ,i want like that in my react component
const { useRef, useState } = React;
const DEBOUNCE_THRESHOLD = 5000;
function App() {
const [messageInput, setMessageInput] = useState("");
const timeoutHandler = useRef(null);
let executeHandlePress = true;
const handleChange = (event) => {
if (timeoutHandler.current) {
clearTimeout(timeoutHandler.current);
}
timeoutHandler.current = setTimeout(() => {
console.log("paused");
}, DEBOUNCE_THRESHOLD);
};
const handleMessagePress = (e) => {
if (!executeHandlePress) {
// if flag false, return
return;
} else {
console.log("composing"); // if true execute
executeHandlePress = false; // toggle flag to false
setTimeout(() => {
executeHandlePress = true; // reset after 5 seconds
}, DEBOUNCE_THRESHOLD);
}
};
const handleMessageChange = (message) => {
setMessageInput(message);
};
const handleMessagePress1 = (e) => {
if (e.key === "Enter" || e === "send") {
console.log("sendMessage");
}
};
return (
<React.Fragment>
<input
value={messageInput}
type="text"
id="messageInputField"
placeholder="Write your message..."
onKeyPress={(e) => {
handleMessagePress(e);
handleMessagePress1(e);
}}
onChange={(e) => {
handleMessageChange(e.target.value);
handleChange();
}}
/>
</React.Fragment>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
//working snippet in js
let myInput = document.getElementById("messageInputField");
let timer;
let executeHandlePress = true; // flag to watch handle press function execution
if (myInput) {
myInput.addEventListener("keyup", () => {
clearTimeout(timer);
timer = setTimeout(stop, 5000);
});
}
const stop = () => {
console.log("user stop typing");
}
const handleMessagePress = (e) => {
if (!executeHandlePress) { // if flag false, return
return;
}
console.log("user is typing"); // if true execute
executeHandlePress = false; // toggle flag to false
setTimeout(() => {
executeHandlePress = true; // reset after 5 seconds
}, 5000);
}
<input placeholder="type your message" id="messageInputField" onKeyPress=" handleMessagePress(event)" />
CodePudding user response:
When you set state in React, it causes your component function to be called again to re-render the component. Each time you render, you're resetting your executeHandlePress as it is being redeclared here:
let executeHandlePress = true;
As a result, whatever you do to this variable in this particular snapshot/render won't persist in the next render, as it will be redeclared. To help deal with this, you can create a ref:
const executeHandlePress = useRef(true);
This way your boolean value will persist across multiple renders. When using a ref, you can refer to your boolean using executeHandlePress.current
: