-1

I am working on a react application. I have a button which call a function inside which I change a state of my app. When a button is clicked, I want to keep on changing the state till the button is again clicked (to stop). Currently I am doing it like this

state = {

        startX:0

    }
changeX = () => {
        //console.log("changex")

        this.setState({startX: this.state.startX + (1/25)} , ()=>{
            console.log(this.state.startX)
            this.changeX()
        })
    }

<button onClick={this.changeX.bind(this)}>Change</button>

I get an error saying

Maximum update depth exceeded. This can happen when a component 
repeatedly calls setState inside componentWillUpdate or 
componentDidUpdate. React limits the number of nested updates 
to prevent infinite loops.
EdG
  • 1,947
  • 5
  • 34
  • 74
  • why are you calling `this.changeX()` inside the method `changeX()`? That is the reason to blow up.. What are you trying to do can be done using `setInterval` function.. Call the method from there, not in the same place .. – Arup Rakshit Aug 25 '18 at 17:03
  • I want to change the value as soon as it get a new value. Reason I am doing this is, I am moving a line based on the value. To make the line movement (in x direction decided by startX) smooth, I want to change the startX continuously. – EdG Aug 25 '18 at 17:08
  • It would not be smooth. Your computer can do billions of calculations per second. If you let the computer update the value as fast as it can, the line would move faster than you can see it. Try something like `setTimeout( () => this.changeX(), 50 )` and adjust the number until the speed is as you like it. – JJJ Aug 25 '18 at 17:12

1 Answers1

0

This error is thrown by react because you are producing a stack overflow by calling this.changeX recursivly with no exit condition.

Basically you are doing this:

function foo() {
  foo()
}

foo() 

This means, as soon as you call foo() once, the Programm will run forever since it won't stop calling itself.

This is as if you had a while(true) loop with no break.

You can avoid this problem by using:

setInterval(function, timeout)

Example:

class SomeComponent extends React.Component {
  state = {
    x: 0
  }

  startAnimation = () => {
    const interval = setInterval(() => {
      this.setState({ x: this.state.x + 50 })

      if(x > 500) {
        clearInterval(interval) 
      }
    }, 50)
  }

  render() {
     return <button onClick={startAnimation}>Click me!</button>
  }
}

This example will change the x value every 50 milliseconds, by 50. You can adjust these values like you want of course. But the important part is that if statement in the setInterval function, it will stop the animation when the value is where you want it.

Resources on setInterval: https://www.w3schools.com/jsref/met_win_setinterval.asp

Patrick Hollweck
  • 2,252
  • 2
  • 17
  • 23