最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin1浏览0评论
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....

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论