Mote Zart
Mote Zart

Reputation: 960

setState inside setInterval not behaving as expected

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

Answers (1)

Robert Cooper
Robert Cooper

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

Related Questions