Home > Enterprise >  deliberate infinite loop in useEffect keeps running after component unload?
deliberate infinite loop in useEffect keeps running after component unload?

Time:10-01

I need to have an infinite loop inside a useEffect for a continual process, however when the component gets unloaded the loop keeps going, I also have issues with the setTimeout cleanup and setTimeout violations in the console .. I have tried to use a cleanup function but to no avail?

  function delay(time) {
    return new Promise((resolve) => setTimeout(resolve, time));
  }

useEffect(() => {
animate();
    const animate = async (dates) => {
      let i = 0;
      await delay(5000);
      while (true) {
        console.log("setting");        
        await delay(1500);
        if (i === dates.length - 1) {
          i = 0;
        } else {
          i  ;
        }
      }     
    };
  }, []);

CodePudding user response:

The other answer's close, but if you want it to run continuously, what you need is setInterval() (1). While also saving its ID to clear it on clean up.

useEffect(() => {
  let interval;
  animate();
  const animate = (dates) => {
    let i = 0;
    interval = setInterval(() => {
      console.log("setting");
      if (i === dates.length - 1) {
        i = 0;
      } else {
        i  ;
      }
    }, 1500)    
  };
  return () => clearInterval(interval)
}, []);

CodePudding user response:

You need to keep the timeout in memory and clear it in the cleanup function of the effect.

Here is a simplified example (also see jsfiddle):

function Animate() {
  const [i, setI] = useState(1)
  
  useEffect(() => {
    const timeout = setTimeout(() => setI(v => v   1), 100)
    return () => clearTimeout(timeout)
  }, [i]) // Be sure to include `i` in dependency array

  return <>{i}</>
}

As others suggested, using an interval instead of a timeout will work too. Maybe even better.

  • Related