Home > Back-end >  How can I get useEffect to work inside of my function?
How can I get useEffect to work inside of my function?

Time:10-08

Currently, I am trying to build a timer, but it stops after one second. I am trying to use hooks in React and I am trying to figure out how to implement useEffect into my startTimer function so it can countdown.

function InputTimer() {
  const [timerOn, setTimerOn] = useState(false);
  const [timerStart, setTimerStart] = useState(0);
  const [timerTime, setTimerTime] = useState(0);

  let timer;

  const startTimer = () => {
    setTimerOn(true);
    setTimerStart(0);
    setTimerTime(0);

    timer = setInterval(() => {
      const newTime = timerTime - 1;

      if (newTime >= 0) {
        setTimerTime(newTime);
      } else {
        clearInterval(timer);
        setTimerOn(false);
        alert("Countdown Ended");
      }
    }, 1000);
  }
}

CodePudding user response:

It appears your code is working.

However, you just set the time to be zero, so after a second, it exits.

To properly test, your code, set the start time to 10 seconds: setTimerTime(10);

Full Code

function InputTimer() {
  const [timerOn, setTimerOn] = useState(false);
  const [timerStart, setTimerStart] = useState(0);
  const [timerTime, setTimerTime] = useState(0);

  let timer;

  const startTimer = () => {
    setTimerOn(true);
    setTimerStart(10); // Change this line
    setTimerTime(0);

    timer = setInterval(() => {
      const newTime = timerTime - 1;

      if (newTime >= 0) {
        setTimerTime(newTime);
      } else {
        clearInterval(timer);
        setTimerOn(false);
        alert("Countdown Ended");
      }
    }, 1000);
  }
}

CodePudding user response:

You've closed over the timerTime value in the interval callback scope, it never changes.

Here's a minimal example of your logic that runs:

Split the logic up, use the interval callback to decrement the time and use a useEffect hook to check the termination condition. Use a React ref to store the timer reference.

function InputTimer() {
  const [timerTime, setTimerTime] = useState(10);

  const timerRef = useRef();

  useEffect(() => {
    return () => clearInterval(timerRef.current);
  }, []);

  useEffect(() => {
    if (timerTime <= 0) {
      clearInterval(timerRef.current);
      alert("Countdown Ended");
    }
  }, [timerTime]);

  const startTimer = () => {
    setTimerTime(10);

    timerRef.current = setInterval(() => {
      setTimerTime(time => time - 1);
    }, 1000);
  }

  return (
    <>
      <div>Time: {timerTime}</div>
      <button type="button" onClick={startTimer}>Start</button>
    </>
  )
}

Edit how-can-i-get-useeffect-to-work-inside-of-my-function

  • Related