0

As this stackoverflow answer says, I tried to create a countdown timer for my project like below.

constructor(props: Object) {
  super(props);
  this.state ={ timer: 3,hideTimer:false}
}

componentDidMount(){
  this.interval = setInterval(
    () => this.setState({timer: --this.state.timer}),
    1000
  );
}

componentDidUpdate(){
  if(this.state.timer === 0){
    clearInterval(this.interval);
    this.setState({hideTimer:true})        
  }
}

render() { 
  return (
    <View style={{ flex: 1, justifyContent: 'center', }}>
      <Text> {this.state.timer} </Text>
    </View>
 )
}

However after adding setState into componentDidUpdate function, I stated to get below error,

Invariant Violation: Maximum update depth exceeded

Since I'm only trying to get state under componentDidMount if and only if time equals to 0, I don' understand why I get above error because that code only execute only once and after state set, timeinterval get clear as well.

So can someone explain please what I'm doing wrong here? Thank you.

Community
  • 1
  • 1
Ryan94
  • 321
  • 1
  • 5
  • 17
  • 1
    Just a side note, you should never do something like `--this.state.time`, since it mutate directly the state. In your case, you should do `timer: this.state.timer - 1`. – Antoine Grandchamp Oct 16 '18 at 18:38

2 Answers2

2

The issue is your componentDidUpdate logic:

componentDidUpdate(){
  if(this.state.timer === 0){
    clearInterval(this.interval);
    this.setState({hideTimer:true})        
  }

When you call this.setState({hideTime: true}) your componentDidUpdate logic gets revisited and since this.state.timer will be 0 at that point as you have not restarted the timer (componentDidMount will only be called once after your initial render and not on update)

Not entirely sure what you are trying to accomplish and what you're working with but this change should help

componentDidUpdate(){
  if(this.state.timer === 0 && !this.state.hideTimer){
    clearInterval(this.interval);
    this.setState({hideTimer:true})        
  }

so by setting hideTime:true and then checking against that value you can prevent the infinite setState loop. If that check doesn't work for what you're trying to accomplish then you'll have to use different logic but hopefully you get the idea.

Robbie Milejczak
  • 5,664
  • 3
  • 32
  • 65
0

Answer to your question is in description of error itself. it says:

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.

Which means you should not update state in componentDidUpdate hook.

If you just remove this.setState({hideTimer:true}) from componentDidUpdate(), this should work fine.

https://codesandbox.io/embed/l50586k4q

Sandip Nirmal
  • 2,283
  • 21
  • 24
  • 1
    you can update state in your `componentDidUpdate` method, but you have to realize that if you do the method will be called again and so you need to have logic in place to prevent it from setting state as a response to setting state as that will cause the infinite loop – Robbie Milejczak Oct 16 '18 at 18:37