Reputation: 960
I want a simple counter to update the state every second (or whatever). I'm using setInterval
because I don't know how else to do it. I want the state change to be reflected in the markup and change on the screen.
Currently the idea works without setState
, but as soon as setState
is added values become undefined, values jump incorrectly, and infinite loops occur.
this.state = {
numberLine: {
1: {
end: 42
}
}
}
I change the value and then reassign the entire value of the object
counter(start) {
const that = this
const copy = _.cloneDeep(this.state.numberLine)
function timer() {
copy['1'].end = start
that.setState({
numberLine: copy
})
}
let counter = setInterval(timer, 1000)
}
renderCustomMarkUp(num) {
this.counter(num)
return (
<span>
{this.state.numberLine['1'].end}
</span>
)
}
// call in render
{this.renderCustomMarkUp(this.state.numberLine['1'].end)}
I'd expect the value to update by one each section here. Then when printing the state expect to see the value increase. Instead, I get either gibberish like the same number with occasional jumps, or it freezes. Check this demo out. Make sure to let the timer get to at least 55-60 before leaving.
It doesn't seem this setInterval
thing is the correct approach. How should I fix it?
Upvotes: 0
Views: 3656
Reputation: 2240
I've fixed your demo in a Code Sandbox: https://codesandbox.io/s/fragrant-dawn-kwp1w
The issue you were running into was that you were calling setInterval(timer, 1000)
on every render. So every time you updated state, you were calling setInterval(timer, 1000)
, which was setting up many timers that would get triggered at 1s intervals.
Instead I've changed your component so that it only calls setInterval(timer, 1000)
when the component mounts and i'm also using state directly when it comes time to increment the value of your counter.
Upvotes: 4