The following is most likely a fundamental question. I have the following class. The value of this.isRunning
is updated to true
in start()
but after running start()
at stop()
the value is still false
. What is the reason for that? This happens when the class is imported into a React component and instantiated.
The latest version of Stopwatch
as used in a React component can be seen below:
import moment from "moment";
export default class Stopwatch {
constructor() {
console.log("run");
this.isRunning = false;
this.lastUpdateTime = 0;
this.totalDuration = 0;
this.interval = null;
}
start() {
if (this.isRunning) {
return console.error("Stopwatch is already started");
}
console.log("Stopwatch started");
this.lastUpdateTime = window.performance.now();
this.isRunning = true;
console.log(this.isRunning);
this.interval = setInterval(() => {
this.totalDuration += window.performance.now() - this.lastUpdateTime;
this.lastUpdateTime = window.performance.now();
}, 100); // update about every 100 ms
}
stop() {
console.log(this.isRunning)
if (!this.isRunning) {
return console.error("Stopwatch is already stopped");
}
console.log("Stopwatch stopped");
console.log("Stopwatch duration:", this.getFormattedDuration());
this.isRunning = false;
clearInterval(this.interval);
}
reset() {
console.log("Stopwatch reset");
this.isRunning = false;
this.lastUpdateTime = 0;
this.totalDuration = 0;
clearInterval(this.interval);
}
formatTime = (ms) => moment(ms).format("mm:ss.S");
getFormattedDuration() {
if (this.lastUpdateTime === 0) {
return "00:00.000";
}
return this.formatTime(this.totalDuration);
}
}
First, the stopwatch is started. Then it is stopped, and finally, reset.
The console output is the following:
Here is a stripped-down version of the original React component where the issue still occurs:
import React from 'react';
import { Button, Row, Col } from 'antd';
import { I18n } from 'aws-amplify';
import Stopwatch from '../../../../../utils/Stopwatch';
export default function TenMeter(props) {
const stopwatch = new Stopwatch();
const startTrial = async (index) => {
stopwatch.start();
}
const completeTrial = async (index) => {
stopwatch.stop();
resetParameters();
}
const resetTrial = async (index) => {
resetParameters();
}
const resetTest = (index) => {
resetParameters();
}
/**
* Reset parameter values.
*/
const resetParameters = () => {
stopwatch.reset();
}
function getTrialsButtonGroup(index) {
return (
<Row key={index} gutter={[16, 16]}>
<Col xs={{ span: 24, offset: 0 }} lg={{ span: 24, offset: 0 }}>
<span>{I18n.get('Trial')} {index + 1}</span>
<Button style={{ marginLeft: "10px" }} onClick={() => startTrial(index)}>{I18n.get('Start')}</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => resetTrial(index)}>{I18n.get('Reset')}</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => completeTrial(index)}>{I18n.get('Stop')}</Button>
</Col>
</Row>
)
};
return (
<div>
{getTrialsButtonGroup(0)}
</div>
);
}
When used in the above React component, Stopwatch
has several instances initialized as it can be seen that the constructor is run several times.
In this JSFiddle snippet the constructor runs only once but the same issue occurs when stopwatch.stop()
is triggered using the console.