javascript - setTimeout() function is not detecting a state change and keeps executing the recursive function - Stack Overflow

useEffect(() => {playLoop();}, [state.playStatus]);const playLoop = () => {if (state.playStatus)

useEffect(() => {
  playLoop();
}, [state.playStatus]);

const playLoop = () => {
  if (state.playStatus) {
    setTimeout(() => {
      console.log("Playing");
      playLoop();
    }, 2000);
  } else {
    console.log("Stopped");
    return;
  }
};

Output: 
Stopped
// State Changed to true
Playing
Playing
Playing
Playing
// State Changed to false
Stopped
Playing // This is the problem, even the state is false this still goes on execute the Truthy stalemate
Playing
Playing

I am working on react-native and I want the recursion to stop when the state value bees false. Is there any other way I can implement this code I just want to repeatedly execute a function while the state value is true. Thank you

useEffect(() => {
  playLoop();
}, [state.playStatus]);

const playLoop = () => {
  if (state.playStatus) {
    setTimeout(() => {
      console.log("Playing");
      playLoop();
    }, 2000);
  } else {
    console.log("Stopped");
    return;
  }
};

Output: 
Stopped
// State Changed to true
Playing
Playing
Playing
Playing
// State Changed to false
Stopped
Playing // This is the problem, even the state is false this still goes on execute the Truthy stalemate
Playing
Playing

I am working on react-native and I want the recursion to stop when the state value bees false. Is there any other way I can implement this code I just want to repeatedly execute a function while the state value is true. Thank you

Share Improve this question asked Sep 1, 2020 at 5:29 SujitSujit 615 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

Rather than having a playStatus boolean, I'd save the interval ID. That way, instead of setting playStatus to false, call clearInterval. Similarly, instead of setting playStatus to true, call setInterval.

// Can't easily use useState here, because you want
// to be able to call clearInterval on the current interval's ID on unmount
// (and not on re-render) (interval ID can't be in an old state closure)
const intervalIdRef = useRef(-1);
const startLoop = () => {
  // make sure this is not called while the prior interval is running
  // or first call clearInterval(intervalIdRef.current)
  intervalIdRef.current = setInterval(
    () => { console.log('Playing'); },
    2000
  );
};
const stopLoop = () => {
  clearInterval(intervalIdRef.current);
};
// When ponent unmounts, clean up the interval:
useEffect(() => stopLoop, []);

The first thing you should do is make sure to clear the timeout when the state changes to stopped or otherwise check the state within the timeout callback function.

But the problem does not seem to be with the setTimeout code only by itself, but rather that this playLoop is also being called too many times. You should add a console.log with a timestamp right at the start of your playLoop to confirm or disprove this. And to find out where it is called from, you could use console.trace.

const playLoop = () => {
  console.log(new Date(), ': playLoop called')
  console.trace(); // optional
  if (state.playSt....

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745458543a4628602.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信