xuanyue
xuanyue

Reputation: 1428

React useEffect hook doesn't clear interval

I'm trying to build a simple count down timer using react hooks to count down 3 seconds. But after 3 seconds UI stop rendering but in console.log I can still is prints out every second. Why is the second array parameter in useEffect doesn't prevent this from happening?

code sandbox

function CounterGame() {
  const [timeout, setTimeout] = React.useState(3);

  React.useEffect(() => {
    let id = window.setInterval(() => {
      if (timeout > 0) {
        setTimeout(x => x - 1 );
      }
      // this line keep executing even it timeout reach 0
      console.log("in setInterval", timeout);
    }, 1000)

    return () => {
      window.clearInterval(id);
    }
  }, [timeout])
  return (
    <div className="App">
      See instructions.
      <h1>{timeout} seconds</h1>
      {!timeout && <button>Click</button>}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<CounterGame />, rootElement);

Upvotes: 2

Views: 1900

Answers (2)

WebbH
WebbH

Reputation: 2422

According to the React docs:

This is why React also cleans up effects from the previous render before running the effects next time.

Based on this, I believe that the cleanup function is not run until the next iteration of the useEffect. In your example, after timeout hits 0, the useEffect will run 1 more time, setting up a new interval, but because timeout is 0, it will not update the state, so the useEffect won't be called on the next render. That means the cleanup function never gets called for that last iteration.

Upvotes: 3

Murali Kollati
Murali Kollati

Reputation: 149

This may works for you:

clearIntervel when timeOut is zero by adding condition in useEffect

React.useEffect(() => {
      let id = window.setInterval(() => {
        if (timeout > 0) {
          setTimeout(x => x - 1 );
        }

    //clearIntervel here
        if(timeout == 0){
            window.clearInterval(id);
        }

        // this line keep executing even it timeout reach 0
        console.log("in setInterval", timeout);
      }, 1000)
  
      return () => {
        window.clearInterval(id);
      }
    }, [timeout])

Upvotes: 5

Related Questions