Last active
January 27, 2019 03:30
-
-
Save sairamkrish/35351eddec2a61d0654650af70e0d0c2 to your computer and use it in GitHub Desktop.
Simple countdown timer with ReactJs with callback support. This can be plugged into any ReactJS ecosystem like Redux, Flux. This also provides localStorage support to restore when browser crashes. Code explanation is provided here - https://medium.com/@sairamkrish/reactjs-countdown-timer-with-support-for-callbacks-browsercrash-and-optimal-render…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react'; | |
import './Timer.scss'; //Have your own styling | |
import { Row, Col } from 'reactstrap'; | |
export class Timer extends Component { | |
constructor(props){ | |
super(props); | |
this.state = { | |
remainingMinutes: 0, | |
remainingSeconds: 0 | |
}; | |
} | |
updateRemainMinutesAndSeconds(timeRemainingInSeconds){ | |
let remainingMinutes = Math.floor(timeRemainingInSeconds/60); | |
let remainingSeconds = timeRemainingInSeconds % 60; | |
this.setState({ | |
remainingMinutes, | |
remainingSeconds | |
}); | |
} | |
countDown(timeRemainingInSeconds,shouldSkipCallback){ | |
this.setState({ | |
timeRemainingInSeconds | |
}); | |
if (!shouldSkipCallback && timeRemainingInSeconds % 60 === 0) { | |
this.props.onEveryMinute(1); | |
} | |
if (timeRemainingInSeconds === 0){ | |
this.props.onCompletion(); | |
} | |
localStorage.setItem('timeRemainingInSeconds',timeRemainingInSeconds); | |
if(timeRemainingInSeconds > 0){ | |
this.updateRemainMinutesAndSeconds(timeRemainingInSeconds); | |
timeRemainingInSeconds = timeRemainingInSeconds-1; | |
this.setTimeoutId = setTimeout(this.countDown.bind(this,timeRemainingInSeconds, false), 1000); | |
} | |
} | |
compareServerTimeAndComponentTimeAndUpdateServer(serverSideTimeRemainingInSeconds){ | |
let componentTimeRemainingInSeconds = localStorage.getItem('timeRemainingInSeconds'); | |
if(componentTimeRemainingInSeconds && componentTimeRemainingInSeconds < serverSideTimeRemainingInSeconds) { | |
let differenceInMinutes = Math.floor((serverSideTimeRemainingInSeconds - componentTimeRemainingInSeconds)/60) | |
if(differenceInMinutes>0){ | |
this.props.onEveryMinute(differenceInMinutes) | |
} | |
return componentTimeRemainingInSeconds; | |
} | |
return serverSideTimeRemainingInSeconds; | |
} | |
componentWillReceiveProps(nextProps){ | |
if(this.props.timeRemainingInSeconds !== nextProps.timeRemainingInSeconds){ | |
let timeRemainingInSeconds = this.compareServerTimeAndComponentTimeAndUpdateServer(nextProps.timeRemainingInSeconds); | |
this.countDown(timeRemainingInSeconds,true); | |
} | |
} | |
componentWillUnmount(){ | |
clearTimeout(this.setTimeoutId); | |
} | |
render(){ | |
return ( | |
<div className='timer'> | |
<div> | |
<Row> | |
<Col> | |
<div className='font-weight-bold lead number-display'> | |
{ | |
this.state.remainingMinutes>9? | |
this.state.remainingMinutes:'0'+this.state.remainingMinutes | |
}:{ | |
this.state.remainingSeconds>9? | |
this.state.remainingSeconds:'0'+this.state.remainingSeconds | |
} | |
</div> | |
</Col> | |
</Row> | |
<Row> | |
<Col> | |
<div className='info'>remaining</div> | |
</Col> | |
</Row> | |
</div> | |
</div> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment