devYuraKim / react

udemy - jonas schmedtmann
0 stars 0 forks source link

Re10-react-quiz > src > components > Timer.js | timer decreasing by 2 #15

Closed devYuraKim closed 2 months ago

devYuraKim commented 2 months ago

I'm suspecting React.StrictMode and when I commented it out, timer did work normally. However, I think it's more of a workaround than a solution.

index.js

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

App.js

case "countdown":
      return {
        ...state,
        time: state.time - 1,
      };

Timer.js

function Timer({ dispatch, time }) {
  useEffect(
    function () {
      setInterval(() => dispatch({ type: "countdown" }), 1000);
    },
    [dispatch]
  );
  return <div>{time}</div>;
}
devYuraKim commented 2 months ago

TL;DR: cleanup interval with clearInterval

function Timer({ dispatch, time }) {
  useEffect(
    function () {
      const timer = setInterval(() => dispatch({ type: "countdown" }), 1000);

      return () => {
        clearInterval(timer);
      };
    },
    [dispatch]
  );
  return <div className="timer">{time}</div>;
}

Problem: Double Invocation of useEffect

Without a cleanup function, here's what happens:

Solution: clearInterval

The cleanup function ensures that when useEffect runs for the second time, it clears the first interval before setting up a new one. Here's the process:

  1. When useEffect runs, it sets an interval and returns a cleanup function.
  2. When React.StrictMode causes a second invocation, the cleanup function is executed first, clearing the first interval.
  3. Then, the second interval is set up properly. This way, you don't end up with multiple intervals running at the same time, which prevents the timer from decreasing by two.