Earn Asdsa
Earn Asdsa

Reputation: 182

Why `setTimeout` call more than one time when I use `useState`?

I'm so confused about useState in React hooks.

I do not know why console.log in setTimeout function calls more than one time when I use useState.

If I remove useState it normally calls only once. And If I use Class state instead hooks, it normally calls only once as well.

Why is it happened that ? And how can I handle it ?

(here is my code)

import React, { useState, useEffect } from "react";
import "./App.css";

const usePassword = () => {
  const [passwordValue, setPasswordValue] = useState({
    password: "",
    passwordHidden: "",
  });
  let timer = null;

  const trigger = () => {
    clearTimeout(timer);
    timer = setTimeout(() => console.log("end"), 1000);
  };

  const onPasswordChanged = (name, value) => {
    setPasswordValue((prev) => ({ ...passwordValue, passwordHidden: value }));
    trigger();
  };

  return { passwordValue, onPasswordChanged };
};

function App() {
  const { passwordValue, onPasswordChanged } = usePassword();

  const onChanged = (event) => {
    const { name, value } = event.target;
    onPasswordChanged(name, value);
  };
  const onSubmit = () => {
    console.log("submitted!", passwordValue);
  };
  return (
    <div className="App">
      <header className="App-header">
        <input name="password" onKeyUp={onChanged} />
        <button onClick={onSubmit}>Submit</button>
      </header>
    </div>
  );
}

export default App;


Upvotes: 0

Views: 200

Answers (1)

thedude
thedude

Reputation: 9812

Whenever you set the state using useState you get a new timer variable, as the function is called again. This is why your clearTimeout does not work.

You can use a ref to hold on to the value between render cycles:

 const timer = useRef(null);

  const trigger = () => {
    clearTimeout(timer.current);
    timer.current = setTimeout(() => console.log("end"), 1000);
  };

Edit competent-goldstine-jbt3t

Upvotes: 1

Related Questions