1

Here is my program. I created the stopwatch with a start and stop button and everything worked as it should. My next step was to make the stopwatch react to the keyboard, via the spacebar. When I hit the start button, the stopwatch starts running. When I hit the spacebar, instead of the stopwatch just stopping at its current place, it restarts at 0 and begins to count up really quickly. The stop button works as it should.

import React from 'react';

class Home extends React.Component {

    constructor(props) {
        super(props);
        this.state = {milliSecondsElapsed: 0};

        this.handleStopClick = this.handleStopClick.bind(this);
        this.keyPress = this.keyPress.bind(this);
        
    }

    keyPress = (e) => {
        if (e.keyCode == 32){
            handleStopClick();

        }
    }

    getMilliseconds() {
        return ("0" + this.state.milliSecondsElapsed).slice(-2);
    }
    // var number = this.state.milliSecondsElapsed.toString().length;
    getSeconds() {
        var milli = this.state.milliSecondsElapsed;
        var seconds = 0;
        seconds = milli / 100;

        var myTrunc = Math.trunc(seconds);

        myTrunc = myTrunc % 60;

        return ("0" + myTrunc).slice(-2);
    }

    getMinutes() {
        var milli = this.state.milliSecondsElapsed;
        var seconds = 0;
        var minutes = 0;
        seconds = milli / 100;
        minutes = seconds / 60;

        var myTrunc = Math.trunc(minutes);

        return ("0" + myTrunc).slice(-2);
        
    }

    handleStartClick = () => {
        this.setState({
            milliSecondsElapsed: (0)
        });
        this.timer = setInterval(() => {
            this.setState({
                milliSecondsElapsed: (this.state.milliSecondsElapsed + 1)
            });
        }, 10)
    }

    handleStopClick = () => {
        clearInterval(this.timer);
    }

    render() {
        return (
            <div>
                <h1>{this.getMinutes()}:{this.getSeconds()}.{this.getMilliseconds()}</h1>
                <button type="button" onClick={this.handleStartClick}> start </button>
                <button type="button" onClick={this.handleStopClick}> stop </button>
                <input value={this.state.milliSecondsElapsed} onKeyDown={this.keyPress} onChange={this.handleStopClick}/>
            </div>
        );
    }

}

export default Home;

Does anyone see what could be causing this?

2 Answers2

0

I think you can not make clearInterval. Please examine this question

forever_software
  • 145
  • 1
  • 15
0

You attach the keyPress callback to the onKeydown of the input, but when you click the start button to start the stopwatch the button still has focus. Hitting space just hits start again, this is why it "resets" the timer and it starts getting faster, you don't clear the previous intervals so they continue to run. If you shift focus to the input and then hit space it works as expected.

Disabling the start button when the timer starts helps not starting new intervals.

<button
  disabled={this.state.milliSecondsElapsed}
  type="button"
  onClick={this.handleStartClick}
>
  {" "}
  start{" "}
</button>

Edit beautiful-payne-1lxcg

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thanks for describing the issue. That makes sense. I tried your solution and disabled the start button, but it would not react to pressing the spacebar. –  Jul 12 '20 at 05:05
  • @AustinStory Pressing spacebar only does what you want it to if you've clicked or tabbed to the input so it takes focus. Disabling the start button only keeps multiple intervals from being set once stopwatch is started. You could add a ref to the input and manually set focus in the `handleStartClick` callback if you wanted to. An alternative may be to attach the key press listener to the window/document instead. As for your question, "Does anyone see what could be causing this?", have I sufficiently answered it? – Drew Reese Jul 12 '20 at 07:20
  • Yes! I’ll follow your ideas. Thanks! –  Jul 12 '20 at 14:46