Next.js Discord

Discord Forum

How do you add an interval that exits once it reaches `X`?

Answered
Transvaal lion posted this in #help-forum
Open in Discord
Transvaal lionOP
I'm trying to set an interval using setInterval that goes off ever 20ms and once the count reaches 100, it will clear the interval. I'm sure clearInterval has something to do with this, but I'm unclear on how to do it within the pages router.
Answered by Giant panda
export const Counter = () => {
  const [outerValue, setOuterValue] = useState(0)

  useEffect(() => {
    let innerValue = 0

    const interval = setInterval(() => {
      if (innerValue === 10) {
        clearInterval(interval)
        return
      }

      innerValue++

      setOuterValue(innerValue)
    }, 1000)

    return () => {
      clearInterval(interval)
    }
  }, [])

  return <h1>{outerValue}</h1>
}
View full answer

35 Replies

let i = 0; // Initialize i to 0

const interval = setInterval(() => {
  console.log(i); // Replace this with your desired action when the interval runs

  i++; // Increment i

  if (i === 100) {
    clearInterval(interval); // Clear the interval when i reaches 100
  }
}, 20);
cause this isn't a function
Transvaal lionOP
I'm using state variables, is that why it's going to infinity?
Giant panda
You have to share code showing how you are attempting to apply the suggestion
Otherwise it's impossible to give any meaningful help
Transvaal lionOP
    const [percentage, setPercentage] = useState(0)



    const id = setInterval(() => {

        setPercentage(e => e + 1)

        if (percentage == 3)
            clearInterval(id)
        
    }, 1000)


I'm tinkering around, I'm not sure if this code is functiona, but I'll provide it. So, I'm in the process of changing it.
Giant panda
You need to use setInterval within an effect
Otherwise you are leaking and constantly starting new intervals
@Giant panda You need to use setInterval within an effect
Transvaal lionOP
useEffect you mean?
Giant panda
Yes, that's an effect.
@Giant panda Yes, that's an effect.
Transvaal lionOP
That's exactly what I did earlier, but the other Discord user told me otherwise. It's quite confusing.
I've added the useEffect, but once it meets the condition, it keeps going on doesn't stop.
    const [percentage, setPercentage] = useState(0)

    useEffect(() => {
        const id = setInterval(() => {

            setPercentage(e => e + 1)

            if (percentage == 4)
                clearInterval(id)
            console.log(percentage)
        }, 1000)
    }, [])


The console.log prints out 0s
I'm guessing this useEffect fires infinitely, since there's always a state change and it re-renders, redoing the useEffect function again and again.
Giant panda
Your issue here is scoping. The arrow function inside of the effect captures the value of percentage only once, specifically when it gets created.
Thus the value will always be 0 and the condition never met.
Giant panda
export const Counter = () => {
  const [outerValue, setOuterValue] = useState(0)

  useEffect(() => {
    let innerValue = 0

    const interval = setInterval(() => {
      if (innerValue === 10) {
        clearInterval(interval)
        return
      }

      innerValue++

      setOuterValue(innerValue)
    }, 1000)

    return () => {
      clearInterval(interval)
    }
  }, [])

  return <h1>{outerValue}</h1>
}
Answer
Giant panda
You need to keep track of the current value within the closure itself.
Giant panda
First of all it doesn't skip the condition, it works as expected
Second, I just told you that you cannot use the current outerValue inside the arrow function
That's why innerValue exists
Works completely fine
Transvaal lionOP
It should be halting at the condition, but it isn't.
Giant panda
It is
Have you fully refreshed the page to prevent HMR interfering?
Transvaal lionOP
I'll figure it out, don't worry.
Thank you for the help.