Home > Blockchain >  React onSetstate function is calling multiple times
React onSetstate function is calling multiple times

Time:10-08

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:

  • Related