1

The problem: when I remove the dependency array in useEffect the timer never stops. But when I add a dependency array in useEffect the timer gets stuck on 5.

How can I solve this?

const App = () => {
  const [inputValue, setInputValue] = useState("");
  const [target, setTarget] = useState([]);
  const [score, setScore] = useState(0);
  const [timer, setTimer] = useState(5);

  const newQuestion = () => {
    const minimum = 1;
    const maximum = 10;
    const int1 = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
    const int2 = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
    setTarget([int1, int2]);
  };

  const handleReset = () => {
    setScore(0);
    setTimer(5);
  };

  useEffect(() => {
    newQuestion();
  }, [score]);

  useEffect(() => {
    let interval = setInterval(() => {
      setTimer((prev) => {
        if (prev === 1) clearInterval(interval);
        return prev - 1;
      });
    }, 1000);
    return () => clearInterval(interval);
  });

  const handleAnsewer = () => {
    const total = target[0] + target[1];

    if (total === Number(inputValue)) {
      setScore(score + 1);
    } else {
      if (score > 0) {
        setScore(score - 1);
      }
    }

    setInputValue("");

    newQuestion();
  };

  return (
    <>
      <h1>Random Math Quiz</h1>

      <h1> {target.join(" + ")} </h1>

      <h1> Timer: {timer} </h1>

      <input placeholder="Answer" value={inputValue} onChange={(e) => setInputValue(e.target.value)} />

      <div>
        <button disabled={timer === 0} onClick={handleAnsewer}>
          {" "}
          Submit{" "}
        </button>
      </div>

      <div>
        <button onClick={handleReset}> play again </button>
      </div>

      {score === 10 && <h1> (Score: 10 / {score}) Congrate you are master in Math!</h1>}
      {score <= 9 && timer < 1 && <h1> ( Score: 10 / {score}) Oh boy this is the math class!</h1>}
    </>
  );
};

export default App;
3
  • 1
    Please improve the clarity of the question Commented Apr 11, 2022 at 8:38
  • Yes I forgot to save the sandbox codesandbox.io/s/zen-ride-gio2eb here is the quiz app the problem is here when I remove the dependency array in useEfffect the timer is got - an infinite number and the play again button reset the timer to 5 but when I add dependency array in useEffect the timer is stuck on 5. Commented Apr 11, 2022 at 9:12
  • stackoverflow.com/questions/58579426/… Commented Apr 11, 2022 at 17:02

1 Answer 1

1

Change your useEffect containing the setInterval method with this one:

useEffect(() => {
  if (timer > 0){ 
    setTimeout(() => {setTimer(timer - 1)}, 1000)
  }
}, [timer])

I think the approach with setTimeout() is better because you don't need to clear intervals or any of that nonsense.

How it works

  1. Is the condition met?
  2. If yes, update setTimer to new time timer - 1 after 1000ms
  3. timer changes and so it will trigger useEffect and the component will re-render
  4. This will go on until the timer doesn't change. When it hits 0
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.