react-cntdwn icon indicating copy to clipboard operation
react-cntdwn copied to clipboard

How to reset countdown

Open stasb opened this issue 7 years ago • 7 comments

For anyone else wondering, if you want to automatically reset the countdown after it ends, setting a new targetDate prop is not enough. The trick is to set a new value as a key for the <Countdown /> component. I used my current epoch value as the key, which was held in state.

stasb avatar Apr 02 '18 15:04 stasb

Is there any way to prevent the counter from restarting? I'm using redux-form, so state change is forcing the component to refresh. (for example, I have a 2fa page, and if I type a value into a text box, the timer restarts)

jack1012t avatar Jun 21 '18 18:06 jack1012t

So, one way to prevent the refresh when fields change is to pass the time as a prop from the parent:

// Parent component
let timeToExpire = new Date(Date.now() + 5000); // expire in 0:05
this.setState({ timeToExpire: timeToExpire }); // initialize the future time to expire
onExpire = () => {
  let timeToExpire = new Date(Date.now() + 181000); // expire in 3:00
  this.setState({ timerExpired: true });
};

<Child 
  timeToExpire={this.state.timeToExpire}
  onExpire={() => this.onExpire()}
    timerExpired={this.state.timerExpired}
/>

// Child component 
const myForm = ({
  timeToExpire
});
return(
  <CountDownTimer targetDate={timeToExpire} onFinished={onExpire} />
);

jack1012t avatar Jun 22 '18 20:06 jack1012t

@stasb can you post an example of how you accomplished the reset?

jack1012t avatar Jun 28 '18 12:06 jack1012t

@jack1012t

I have this function handling countdown finish:

handleCountdownFinish() {
    const { campaign } = this.props;
    const component = this;

    if (campaign.auto_timer_restart) {
      this.resetCountdown();
      return true;
    }

    setTimeout(function() {
      component.setState({
        countdownComplete: true,
      });
    }, 0.00001);
  }

Then the resetCountdown function looked like this:

resetCountdown() {
    const component = this;

    const newEpoch = this.setCountdownEpoch();

    setTimeout(function() {
      component.setState({
        countdownEpoch: newEpoch,
        countdownComplete: false,
      });
    }, 0.00001);
  }

The function that returned the Countdown component:

getCountdownElement() {
    const { copy, campaign } = this.props;

    const headlineContent = this.returnHeadlineContent();

    return <span className="countdown-label-text">
      {this.returnHeadlineText()}

      <span className="expiry-timer">
        <Countdown targetDate={new Date(parseInt(this.state.countdownEpoch))}
          className="extra-class-lol"
          timeSeparator={':'}
          format={{
            hour: 'hhh',
            minute: 'mm',
            second: 'ss'
          }}
          leadingZero={true}
          onFinished={this.handleCountdownFinish}
          key={this.state.countdownEpoch}
        />
      </span>
    </span>
  }

As I mentioned in my comment, setting the 'key' prop on the Countdown made it work. Also you'll notice I have setTimeout functions there, which I think is a hack I used to make it work, otherwise it rendered weirdly/didn't work.

stasb avatar Jun 28 '18 19:06 stasb

thanks @stasb I'll try to implement this today and let you know how it goes.

jack1012t avatar Jun 29 '18 17:06 jack1012t

@stasb Got it working, thanks so much!

jack1012t avatar Jun 30 '18 11:06 jack1012t

@jack1012t :grin:👌

stasb avatar Jun 30 '18 12:06 stasb