React Timer

Provides updated values to the child components

by jonahe

HTML

<script src="https://unpkg.com/[email protected]/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script>
<div id="root"></div>

Babel + JSX

const Timer = React.createClass({
    getInitialState: function() {
        const {startValue} = this.props;
        return {
            current: startValue,
            runningInterval: null,
            isPaused: false
        };
    },

    componentDidMount: function() {
       this.start();
    },
    
    start: function() {
    	const {changeInterval} = this.props;
      const intervalRef = setInterval(this.doEachInterval, changeInterval);
      this.setState({ runningInterval: intervalRef });
    },
    
    restart: function() {
    	const {startValue} = this.props;
      this.clearInterval();
      this.setState(
      	{ current : startValue },
      	this.start
      );
    },
   	
    togglePaused: function() {
    	const {isPaused} = this.state;
      this.setState({ isPaused: !isPaused });
    },

    doEachInterval: function() {
        const {
            changeInterval,
            changeFunction,
            endCondition,
            onChangeHook,
            onEndHook,
        } = this.props;

        const {current, runningInterval, isPaused} = this.state;
        if(isPaused) return;
        
        if(endCondition(current)) {
            clearInterval(runningInterval);
            onEndHook(current, this);
            return;
        }
        const updatedCurrent = changeFunction(this.state.current);
        onChangeHook(updatedCurrent);
        this.setState({ current: updatedCurrent });
    },
    
    clearInterval: function() {
    	clearInterval(this.state.runningInterval)
    },

    componentWillUnmount: function() {
    		console.log('unmounting');
        this.clearInterval();     
    },

    render: function() {
        const {current, runningInterval} = this.state;
        if(!runningInterval) return <div>No interval running</div>;

        return this.props.children(current, this);
    }
});

/*Timer.propTypes = {
    startValue: PropTypes.number.isRequired,
    changeInterval: PropTypes.number.isRequired,
   ...