0
votes

I have created a timer module from react in which there is one input and three button 1-Start(which starts the timer) 2-Pause(pause the timer) 3-Stop(Stops the timer), Now the problem is that when i input any value and starts the timer and when i press "Stop" button the value becomes 0 but when i again hit the "Start" button the counter starts from the previous value which i clicked at the time of Stop button rather it should start from the value which is written on input field previously. Please check it if you are not understanding what i'm telling.

Code:

<!Doctype html>
<html>
    <head>
        <title>React 1</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>  
        <script src="https://unpkg.com/react-form-with-constraints/dist/react-form-with-constraints.js"></script>
    </head>
    <body>
        <script type="text/jsx">
            var styles = {
                margin: '2em auto',
                width: '300px',
                height: '300px',
                backgroundColor: '#DD4814',
                color: '#ffffff',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'space-around'
            };
            var inputs = {
                position: 'relative',
                bottom: '17%',
                left: '20%'
            }
            var btns = {
                position: 'relative',
                bottom: '7%'
            }
            var btn = {
                backgroundColor: '#ffffff',
                color: '#000000',
                borderColor: '#DEB887',
                borderRadius: '0.4em',
                cursor: 'pointer',
                margin: '0 1em',
                padding: '0.5em',
                display: 'inline-block'
            }
            class Timer extends React.Component {
                constructor (props) {
                    super(props)
                    this.state = 
                        {
                            count: 0,
                            customNumber: 0
                        }
                }
				handleChange (e) {
                    this.setState({	customNumber: e.target.value});
                }
                componentWillUnmount () {
                    clearInterval(this.timer)
                }
                tick () {
                    if (this.state.customNumber) {
						this.setState({
							count: (this.state.customNumber--)
						})
						if (this.state.customNumber <= 0) {
							this.setState({	count: 0})
							clearInterval(this.timer)
							this.setState({ disabled: false })
						}
                    } else {
                        this.setState({count: (this.state.count - 1)})
                    }
                }
				
				display () {
                    return ('0' + this.state.count % 100).slice(-2)
                }
				
                startTimer () {
                    if (this.state.customNumber == "" || isNaN(this.state.customNumber)) 
                    {
                        alert("Please give some value in number");
                    } else {
                        clearInterval(this.timer)
                        this.timer = setInterval(this.tick.bind(this), 1000)
                        this.setState({ disabled: true })
                    }
                }
                stopTimer () {
                    clearInterval(this.timer)
                }
                resetTimer () {
                    clearInterval(this.timer)
                    this.setState({count: 0})
                    this.setState({ disabled: false })
                }
                render () {
                    return (
                    <div style={styles} className='timer'>
                        <h1 style={{fontSize: '4em'}}>{this.display()}</h1>
						<div className="input_text" style={inputs}>
							<label htmlFor="custom_number">Enter number to start timer</label>
							<input type="text" name="custom_number" id="custom_number" value={this.state.inputValue} onChange={this.handleChange.bind(this)} disabled={this.state.disabled} placeholder="Enter b/w 1-100" />
						</div>
                        <div style={btns} className="buttons">
							<button style={btn} type="button" name="start_btn" id="start_btn" onClick={this.startTimer.bind(this)}>Start</button>
							<button style={btn} type="button" name="stop_btn" id="stop_btn" onClick={this.stopTimer.bind(this)}>Pause</button>
							<button style={btn} type="button" name="reset_btn" id="reset_btn" onClick={this.resetTimer.bind(this)}>Stop</button>
                        </div>
                    </div>
                    )
                }
            }
            ReactDOM.render( <Timer />, document.getElementById('root') )
        </script>
        <div id="root"></div>
    </body>    
</html>
1
I can't see onChange={this.handleChange.bind(this)} defined. This might be the issue. Your state --> customCount is not having value from input. - Umesh
I have defined it - user8079593

1 Answers

0
votes

All your code is almost fine, but you need to make some changes to make it work correctly as you expected.

So first, you need to save the last input (number) for the countdown, so let's add lastInput: 0 into your component's state, that state will be filled when your type some number in the input field, so each time you type the lastInput property will change with the value that you set.

Once you have clicked on Stop button, you were doing only this: this.setState({ count: 0 }) but you were forgetting something else, you need to restart the property customNumber too to reset it, so you need to do this: this.setState({ count: 0, customNumber: this.state.lastInput }) where this.state.lastInput has the last value set by the user, that is for avoid to save the input's value into a local variable, so I think it's better to save that value into the component state.

NOTE

If you are using babel in your React component, it will be better using arrow function from ES6, so you can avoid the this.myfunction.bind(this) syntax so you could do it in this way:

taking your code as example it would be like this:

handleChange = (e) => {
  var value = e.target.value;
  this.setState({ customNumber: value, lastInput: value });
}

now you can use the above function without bind

<input className="some-classname" onChange={this.handleChange} />

What happened above ?, so arrow function in ES6 will make the bind process for you, that is magically automatic, it avoid that your functions loose their scope when external elements call your function.

REMEMBER

you can do the above code only if you are using babel to transpile your ES6 code to ES5 to make them understandable to the old browsers.

<!Doctype html>
<html>
    <head>
        <title>React 1</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>  
        <script src="https://unpkg.com/react-form-with-constraints/dist/react-form-with-constraints.js"></script>
    </head>
    <body>
        <script type="text/jsx">
            var styles = {
                margin: '2em auto',
                width: '300px',
                height: '300px',
                backgroundColor: '#DD4814',
                color: '#ffffff',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'space-around'
            };
            var inputs = {
                position: 'relative',
                bottom: '17%',
                left: '20%'
            }
            var btns = {
                position: 'relative',
                bottom: '7%'
            }
            var btn = {
                backgroundColor: '#ffffff',
                color: '#000000',
                borderColor: '#DEB887',
                borderRadius: '0.4em',
                cursor: 'pointer',
                margin: '0 1em',
                padding: '0.5em',
                display: 'inline-block'
            }
            class Timer extends React.Component {
                constructor (props) {
                    super(props)
                    this.state = 
                        {
                            count: 0,
                            customNumber: 0,
                            lastInput: 0
                        }
                }
				handleChange (e) {
                    const value = e.target.value;
                    this.setState({	customNumber: value, lastInput: value});
                }
                componentWillUnmount () {
                    clearInterval(this.timer)
                }
                tick () {
                    if (this.state.customNumber) {
						this.setState({
							count: (this.state.customNumber--)
						})
						if (this.state.customNumber <= 0) {
							this.setState({	count: 0})
							clearInterval(this.timer)
							this.setState({ disabled: false })
						}
                    } else {
                        this.setState({count: (this.state.count - 1)})
                    }
                }
				
				display () {
                    return ('0' + this.state.count % 100).slice(-2)
                }
				
                startTimer () {
                    if (this.state.customNumber == "" || isNaN(this.state.customNumber)) 
                    {
                        alert("Please give some value in number");
                    } else {
                        clearInterval(this.timer)
                        this.timer = setInterval(this.tick.bind(this), 1000)
                        this.setState({ disabled: true })
                    }
                }
                stopTimer () {
                    clearInterval(this.timer)
                }
                resetTimer () {
                    clearInterval(this.timer)
                    this.setState({count: 0, customNumber: this.state.lastInput})
                    this.setState({ disabled: false })
                }
                render () {
                    return (
                    <div style={styles} className='timer'>
                        <h1 style={{fontSize: '4em'}}>{this.display()}</h1>
						<div className="input_text" style={inputs}>
							<label htmlFor="custom_number">Enter number to start timer</label>
							<input type="text" name="custom_number" id="custom_number" value={this.state.inputValue} onChange={this.handleChange.bind(this)} disabled={this.state.disabled} placeholder="Enter b/w 1-100" />
						</div>
                        <div style={btns} className="buttons">
							<button style={btn} type="button" name="start_btn" id="start_btn" onClick={this.startTimer.bind(this)}>Start</button>
							<button style={btn} type="button" name="stop_btn" id="stop_btn" onClick={this.stopTimer.bind(this)}>Pause</button>
							<button style={btn} type="button" name="reset_btn" id="reset_btn" onClick={this.resetTimer.bind(this)}>Stop</button>
                        </div>
                    </div>
                    )
                }
            }
            ReactDOM.render( <Timer />, document.getElementById('root') )
        </script>
        <div id="root"></div>
    </body>    
</html>