Home > Enterprise >  After a button is pressed to start a setInterval(), how do I clearInterval once a condition is met
After a button is pressed to start a setInterval(), how do I clearInterval once a condition is met

Time:02-17

I have an app that starts an interval when a button is pressed. I want to stop the interval after a state reaches 5. I have tried adding the if condition in UseEffect, and tried putting the condition within the function itself, but both don't seem to work. The console.log(sequence) does print successfully in useEffect I can see that the sequence does indeed increase, but it keeps increasing beyond 5 and never 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>)
}

CodePudding user response:

Issue

You are not clearing the interval correctly.

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

...

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

Here interval is a reference to the function, not the actual interval timer id returned from setInterval.

Solution

Store the interval timer id in a React ref to be referenced around the component.

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]);

Also, there's no need to check the sequence value and clear the interval in the plant callback, the useEffect hook with dependency on sequence will handle that. Plant only needs to start the interval.

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

CodePudding user response:

You can use the clearInterval function to stop the interval you had set.

Here is an example;

let counter = 0;

const interval = setInterval(() => {
  counter  ;

  console.log(`Counter = ${counter}`);

  if (counter >= 3) {
    console.log("Interval Stopped");
    clearInterval(interval);
  }
}, 1000);

  • Related