Search code examples
javascriptreactjsshow-hidecountdown

How to hide element after react-countdown-now time up


I'm trying to make a bidding website by ReactJs and here is the problem. I hope the input form will hide after time countdown completed(npm react-countdown-now)

1.I try to setState True or False {this.state.showForm && } but it doesn't work after countdown completed and get error

import React, { Component } from 'react'
import Countdown from 'react-countdown-now';

class Pricebidding extends Component {
  constructor(props) {
     super(props)
     this.state = {
       showForm: true,
     }
     this.renderer = this.renderer.bind(this);
  }

  renderer({ days, hours, minutes, seconds, completed}) {

    if (completed) {
        this.setState({ showForm: false })
        return <span>Time up</span>
    } else {
         this.setState({ showForm: true})   
        return 
        <span>{days}days{hours}hours{minutes}mins{seconds}secs</span>
    }
  }

  render()
     return (
        <div>
            <Countdown date={this.props.endtime} renderer={this.renderer}/>
            {this.state.showForm && <form>
                <input></input>
                <button type="submit">Bid</button>
                <span>{this.state.bidprompt}</span>
            </form> }
        </div>
    );
  }
}

Uncaught Invariant Violation: 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.


Solution

  • you are getting an infinite loop because you are updating the state infinitely,

    renderer -> setState -> renderer -> setState -> ...

    you can fix the problem by rendering the form inside the CountDown component

    class Pricebidding extends Component {
       constructor(props) {
         super(props);
         this.state = {
           bidprompt: '...'
         };
         this.renderer = this.renderer.bind(this);
       }
    
       renderer({ days, hours, minutes, seconds, completed}) {
        if (completed) {
           return <span>Time up</span>;
        } else {
          return (
           <>
              <span>{days}days{hours}hours{minutes}mins{seconds}secs</span>
              <form>
                <input></input>
                <button type="submit">Bid</button>
                <span>{this.state.bidprompt}</span>
             </form>
           </>
          );
        }
      }
    
      render()
        return (
            <Countdown 
               date={this.props.endtime} 
               renderer={this.renderer}
            />
        );
      }
    }
    

    if you want to keep a state in your component, you can use the onComplete property

    class Pricebidding extends Component {
       constructor(props) {
         super(props);
         this.state = {
           showForm: true,
         };
         this.handleComplete = this.handleComplete.bind(this);
       }
    
       handleComplete() {
          this.setState({ showForm: false });
       }
    
       renderer({ days, hours, minutes, seconds, completed}) {
        if (completed) {
           return <span>Time up</span>;
        } else {
          return <span>{days}days{hours}hours{minutes}mins{seconds}secs</span>;
        }
      }
    
      render()
        return (
          <div>
            <Countdown 
               date={this.props.endtime} 
               renderer={this.renderer}
               onComplete={this.handleComplete}
             />
             {this.state.showForm && (
               <form>
                 <input></input>
                 <button type="submit">Bid</button>
                 <span>{this.state.bidprompt}</span>
               </form> 
            )}
          </div>
        );
      }
    }