【问题标题】:After a button is pressed to start a setInterval(), how do I clearInterval once a condition is met按下按钮启动 setInterval() 后,一旦满足条件,如何清除Interval
【发布时间】:2022-02-17 08:55:50
【问题描述】:

我有一个应用程序在按下按钮时会启动一个间隔。 我想在状态达到 5 后停止间隔。 我尝试在UseEffect 中添加 if 条件,并尝试将条件放在函数本身中,但两者似乎都不起作用。 console.log(sequence) 确实在 useEffect 中成功打印我可以看到序列确实增加了,但它一直增加超过 5 并且永远不会 clearInterval

  const [sequence, setSequence] = useState(0)
    
    const interval = () =>{
        setInterval(() => {
            setSequence((prevSequence) => (
                prevSequence+1
            ))
        }, 2000);
    }

    const plant = ()=>{
        interval()
        console.log(sequence)
        if(sequence>5){
           clearInterval (interval)
        }
    }

    useEffect(() => {
        console.log(sequence)
        if(sequence>5){
            return () => clearInterval(interval);
        }
      }, [sequence]);

 return(
    <View style = {styles.container} >
        <Image
            style={{height:500,width:300,}}
            source= {tomato[sequence]}
        />
        <Button 
        title = 'Fertilize Plant' 
        style= {styles.text}
        onPress= {plant}>
        </Button>

    </View>)
}

【问题讨论】:

    标签: react-native react-hooks setinterval clearinterval


    【解决方案1】:

    问题

    您没有正确清除间隔。

    const interval = () => {
      setInterval(() => {
        setSequence((prevSequence) =>  prevSequence + 1)
      }, 2000);
    };
    

    ...

    useEffect(() => {
      console.log(sequence);
      if (sequence > 5) {
        return () => clearInterval(interval);
      }
    }, [sequence]);
    

    这里interval是对函数的引用,不是setInterval返回的实际间隔定时器ID。

    解决方案

    将间隔计时器 id 存储在要在组件周围引用的 React ref 中。

    const intervalRef = useRef();
    
    const interval = () => {
      intervalRef.current = setInterval(() => {
        setSequence((prevSequence) =>  prevSequence + 1)
      }, 2000);
    };
    

    ...

    useEffect(() => {
      const intervalId = intervalRef.current;
    
      // also clear on component unmount
      return () => clearInterval(intervalId);
    }, []);
    
    useEffect(() => {
      if (sequence > 5) {
        clearInterval(intervalRef.current);
      }
    }, [sequence]);
    

    此外,无需检查sequence 值并清除plant 回调中的间隔,依赖于sequenceuseEffect 挂钩将处理该问题。 Plant只需要开始间隔即可。

    const plant = () => {
      interval();
    };
    

    【讨论】:

    • 非常感谢!!!我绝对需要阅读 useRef :/不知道我必须使用它
    • @ArîstonGiltedged 我认为使用useRef 钩子没有要求,但它确实很容易,并且是一种非常好的React 方式来处理它。
    • 嘿@Drew 再次感谢您的解决方案和更多改进。我认为我最大的问题是对计时器 ID 缺乏了解。您的解决方案是目前我知道的唯一方法。
    【解决方案2】:

    您可以使用clearInterval 函数来停止您设置的时间间隔。

    这是一个例子;

    let counter = 0;
    
    const interval = setInterval(() => {
      counter++;
    
      console.log(`Counter = ${counter}`);
    
      if (counter >= 3) {
        console.log("Interval Stopped");
        clearInterval(interval);
      }
    }, 1000);

    【讨论】:

    • 我刚试过,clearInterval 没有出现,甚至 console.log("interval stopped") 我试过在我的代码的 const 间隔函数中添加 clearInterval 函数.我的useEffect里面还有一个clearInterval函数,const plant函数也有clearInterval...但是还是不清除
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2013-08-03
    • 1970-01-01
    • 2010-10-31
    • 2021-09-24
    • 2021-09-11
    相关资源
    最近更新 更多