Javascript ReactJS-将setTimeout()与if/else语句一起使用

Javascript ReactJS-将setTimeout()与if/else语句一起使用,javascript,reactjs,Javascript,Reactjs,我正在使用0点钟时钟工作,我无法使用setTimeout()加入if/else。这是我的密码: React.useEffect(() => { if(props.isOn === true) { if(props.timeLeft <= 0) { setTimeout(function() { if(props.activeClockType === 'Session') { props.handleCl

我正在使用0点钟时钟工作,我无法使用setTimeout()加入if/else。这是我的密码:

React.useEffect(() => {
    if(props.isOn === true) {
      if(props.timeLeft <= 0) {
        setTimeout(function() {
          if(props.activeClockType === 'Session') {
            props.handleClockType('Break');
            props.handleTimeLeft(props.breakLength * 60);
          } else {
            props.handleClockType('Session');
            props.handleTimeLeft(props.sessionLength * 60);
          }
        }, 1000);
      }
      const id = setInterval(count, 1000);
      return () => clearInterval(id);
    }
  });
React.useffect(()=>{
如果(props.isOn==真){
if(props.timeLeft clearInterval(id));
}
});
当时钟转到00:00时,它会停止1秒,然后显示Break(中断),计时器设置为breakLength(中断长度)。很好,但1秒后它不会倒计时,而是改回Session(会话)并计算会话长度

当我删除setTimeout(在CodePen中注释)时,它工作正常,但不会在00:00停止1秒,而是在中断时立即更改看起来很难看的内容

如何在计算其他activeClockType之前使其在00:00停止1秒?

我花了整整一个晚上寻找任何线索,但我仍然不知道哪里出了问题。我尝试将setTimeout与if的每一种可能组合在一起,但效果总是一样的。从我的观点来看,我怀疑我可能应该使用cleartimout,但也尝试了任何组合,结果一无所获

或者我应该尝试另一种方法来运行倒计时,而不是useffect()?之前我在类组件中创建了工作计时器(在CodePen中注释)使用componentWillReceiveProps,但它已被弃用,我试图在其他函数上更改它,但没有任何效果。我不完全理解这个效果挂钩,但这是我唯一能够计数的方法。它比类组件短

代码笔上有我的完整代码吗


提前谢谢。

我想这里有两个问题:

1) 每次使用钩子设置状态时,都会触发React.useffect,如果设置两次状态,React.useffect将触发两次

2) 使用setTimeout替换setInterval以避免更新状态的次数过多

问题如下:

  React.useEffect(() => {
    if(props.isOn === true) {
      if(props.timeLeft <= 0 && !changeClockType) {
        setTimeout(function() {
          if(props.activeClockType === 'Session') {
            props.handleClockType('Break');   // ==> Fired update and then excuted React.useEffect
            props.handleTimeLeft(props.breakLength * 60); //  ==> Fired update again and then excuted React.useEffect again
          } else {
            props.handleClockType('Session');
            props.handleTimeLeft(props.sessionLength * 60);
          }
        }, 1000);
      }
      const id = setTimeout(count, 1000);  // ==> modify setInterval to setTimeout 
      return () => clearInterval(id);
    }

  });
React.useffect(()=>{
如果(props.isOn==真){
如果(props.timeLeft)触发了更新,然后执行React.useffect
props.handleTimeLeft(props.breakLength*60);//=>再次触发更新,然后再次执行React.useffect
}否则{
道具手柄锁类型(“会话”);
手持道具(道具会话长度*60);
}
}, 1000);
}
const id=setTimeout(计数,1000);//=>将setInterval修改为setTimeout
return()=>clearInterval(id);
}
});
我尝试如下修改代码:

let changeClockType = false;  // ==> Should be put here because it couldn't be put in the function component
function Timer(props) {

  const count = () => props.handleTimeLeft(props.timeLeft - 1);

  function startStop() {
    props.handleIsOn(props.isOn === false ? true : false);
  }

  React.useEffect(() => {
    console.log("step 1");
    if(props.isOn === true) {   console.log("step 2");
      if(props.timeLeft <= 0 && !changeClockType) {   console.log("step 3");
        setTimeout(function() {
          if(props.activeClockType === 'Session') {   console.log("step 4");
            changeClockType = true;
            props.handleClockType('Break');   // ==> Fired update and then excuted React.useEffect
            console.log("Change to Break")
            props.handleTimeLeft(props.breakLength * 60); //  ==> Fired update again and then excuted React.useEffect again
            changeClockType = false;
            console.log("Set breakLength")
          } else {   console.log("step 5");
            changeClockType = true;
            props.handleClockType('Session');
            props.handleTimeLeft(props.sessionLength * 60);
            changeClockType = false;
          }
        }, 1000);
      }
      const id = setTimeout(count, 1000);  // ==> modify setInterval to setTimeout 
      return () => clearInterval(id);
    }
  });
让changeClockType=false;//=>应该放在这里,因为它不能放在函数组件中
功能计时器(道具){
常量计数=()=>props.handleTimeLeft(props.timeLeft-1);
函数startStop(){
props.handleIsOn(props.isOn==false?true:false);
}
React.useffect(()=>{
控制台日志(“步骤1”);
if(props.isOn==true){console.log(“步骤2”);
如果(props.timeLeft)触发了更新,然后执行React.useffect
日志(“更改为中断”)
props.handleTimeLeft(props.breakLength*60);//=>再次触发更新,然后再次执行React.useffect
changeClockType=false;
console.log(“设置断开长度”)
}else{console.log(“步骤5”);
changeClockType=true;
道具手柄锁类型(“会话”);
手持道具(道具会话长度*60);
changeClockType=false;
}
}, 1000);
}
const id=setTimeout(计数,1000);//=>将setInterval修改为setTimeout
return()=>clearInterval(id);
}
});

代码不是很干净,但可以很好地运行。

工作得很好!非常感谢。顺便问一下,为什么在函数之外声明此let?我试过了,但如果在里面声明它实际上不起作用。如果声明为useState钩子,它就可以工作。什么是更好的正常声明,因为如果将changeClockType放入计时器函数中,当props.handleClockType('Break')正在执行时,函数计时器将执行,并且changeClockType的值将被初始化。执行计时器函数后,将执行props.handleTimeLeft(props.breakLength*60)。您可以尝试代码并查看登录控制台。