pughpugh / react-countdown-clock

HTML5 canvas countdown clock React component
ISC License
187 stars 83 forks source link

How to restart the timer? #42

Open akhilkurnool opened 6 years ago

akhilkurnool commented 6 years ago

How to restart on setState or any other condition or props change, I have tried to re-render the whole component using forceUpdate() but it doesn't seem to work. Using this clock for OTP countdown, need to reset when the user resend OTP.

akhilkurnool commented 6 years ago

One way I found was using history to redirect to same page.

sjmp commented 6 years ago

This is still an open issue! The inability to restart this component is a real pain.

pughpugh commented 6 years ago

No need to be quite so dramatic @sjmp . What action are you proposing would reset the timer?

I've not looked at this in a while, but I believe if the seconds prop changes, the timer will restart. It maybe that there is a bug around this that needs fixing (#45) and it might not be of use if you need to reset it to the same time.

If I find some time over the xmas holidays I will take a look.

zaidchauhan commented 6 years ago

@sjmp @pughpugh Setting the same time again will not work. You can do something like this

Initial state from seconds received in props or fixed. You may also use default props instead ternary operator

constructor(props){
    super(props);

    this.state = {
      seconds: this.props.seconds ? this.props.seconds : 60,
    };
  }

Set state by adding fraction.

this.setState({
     seconds: this.getNewSeconds()
 })
getNewSeconds = () => {
    //Note: This library only restart timer when we supply different seconds
    if(this.props.seconds !== this.state.seconds) {
      return this.props.seconds;
    }else {
      return this.props.seconds + 0.0000001;
    }
pughpugh commented 6 years ago

45 has been fixed as well a couple of other related bugs. I'm not convinced this fully meets the requirements of resetting the timer, but might at least support a workaround for some people.

miso2018 commented 6 years ago

Seems like a badly needed feature.

You'll have to find a way to call the following internally:

        this._clearBackground()
        this._seconds = this.props.seconds
        this._stopTimer()
        this._setupTimer()

I needed a timer that automatically reset on complete:

class ResettableTimer extends ReactCountdownClock {
  constructor(props){
    super(props)
    this._handleComplete = () => {
        // Do what you need
        this._clearBackground()
        this._seconds = this.props.seconds
        this._stopTimer()
        this._setupTimer()
    }
  }
}
VilliGunn commented 6 years ago

Might not be the best approach but here is what I did to force the component to re-render and therefore restart.

import React, { Component } from 'react'
import CountDown from 'react-countdown-clock'
class CountDownTest extends Component {
  constructor() {
    super()
    this.state = {
      completions: 0
    }
  }

  onComplete = () => {
    this.setState(
      {
        completions: this.state.completions + 1
      },
      () => console.log('completions', this.state.completions)
    )
  }

  render() {
    return (
      <div>
        <CountDown
          key={this.state.completions}
          seconds={15}
          color="#000"
          alpha={0.9}
          size={300}
          onComplete={this.onComplete}
        />
      </div>
    )
  }
}

export default CountDownTest

this.state.completions updates every time the countdown is completed and by using a state property that is always changing as the value for the key attribute, forces the component to re-render.

JeremyEllingham commented 5 years ago

@VilliGunn Great solution, I'd even suggest adding it in the Readme as part of an FAQ section if there is no progress on implementing this feature into the base component.

epozsh commented 5 years ago

@pughpugh What if you will add new prop countDownStartedAt and on

componentDidUpdate(prevProps) {
    if (prevProps.seconds !== this.props.seconds || prevProps.countDownStartedAt!== this.props.countDownStartedAt) {
      this._seconds = this.props.seconds;
      this._stopTimer();
      this._setupTimer();
    }

and the only thing we have to do is change countDownStartedAt prop to restart it.

timgreen commented 2 years ago

Late to the party, but note for the people are still seeking for simple solution.

Like https://www.npmjs.com/package/react-countdown#key mentioned, just set a new key to reset the component to restart the countdown.