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;
AKX
  • 152,115
  • 15
  • 115
  • 172
ahmad
  • 25
  • 3
  • 1
    Please improve the clarity of the question – Gass Apr 11 '22 at 08:38
  • Yes I forgot to save the sandbox https://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. – ahmad Apr 11 '22 at 09:12
  • https://stackoverflow.com/questions/58579426/in-useeffect-whats-the-difference-between-providing-no-dependency-array-and-an – JASBIR SINGH Apr 11 '22 at 17:02

1 Answers1

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
Gass
  • 7,536
  • 3
  • 37
  • 41