How do you add an interval that exits once it reaches `X`?
Answered
Transvaal lion posted this in #help-forum
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>
}35 Replies
@Transvaal lion 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`.
this has nothing to do with pages router, this is basic JS
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);@@ts-ignore js
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);
Transvaal lionOP
I've done this already and am not sure why it passes the if condition into infinity.
@Transvaal lion I've done this already and am not sure why it passes the if condition into infinity.
I've tried it and it works perfectly
@@ts-ignore js
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);
Transvaal lionOP
Also, where are you using this function? I tried adding a
useEffect hook and using it inside, but it keeps adding to infinity@Transvaal lion Also, where are you using this function? I tried adding a `useEffect` hook and using it inside, but it keeps adding to infinity
there is no need to call this
intervalcause 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
0sI'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 ts
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>
}
Transvaal lionOP
It goes past the condition and the console log keeps printing out
0s.console.log(outerValue)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 functionThat's why
innerValue existsWorks 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.