Skip to main content

timer-stopwatch

Please give me a short React Typescript (functional components, can use hooks): 6. Timer or Stopwatch: Make a timer or stopwatch with start, stop, and reset controls.

Certainly! Below is a simple example of a stopwatch using React with TypeScript. This stopwatch includes start, stop, and reset functionalities.

import React, { useState, useEffect } from 'react';

const Stopwatch: React.FC = () => {
const [time, setTime] = useState<number>(0);
const [isRunning, setIsRunning] = useState<boolean>(false);

useEffect(() => {
let interval: ReturnType<typeof setInterval> | null = null;

if (isRunning) {
interval = setInterval(() => {
setTime((prevTime) => prevTime + 10);
}, 10);
} else if (!isRunning && time !== 0) {
clearInterval(interval!);
}

return () => interval && clearInterval(interval);
}, [isRunning, time]);


return () => interval && clearInterval(interval);
}, [isRunning, time]);

const start = () => setIsRunning(true);
const stop = () => setIsRunning(false);
const reset = () => {
setIsRunning(false);
setTime(0);
};

return (
<div>
<h2>Stopwatch</h2>
<div>
<span>{("0" + Math.floor((time / 60000) % 60)).slice(-2)}:</span>
<span>{("0" + Math.floor((time / 1000) % 60)).slice(-2)}.</span>
<span>{("0" + ((time / 10) % 100)).slice(-2)}</span>
</div>
<button onClick={start} disabled={isRunning}>Start</button>
<button onClick={stop} disabled={!isRunning}>Stop</button>
<button onClick={reset}>Reset</button>
</div>
);
};

export default Stopwatch;

Here's what the code does:

  • The time state keeps track of the elapsed time in milliseconds.
  • The isRunning state indicates whether the stopwatch is running.
  • The useEffect hook sets up an interval when the stopwatch starts and clears it when the stopwatch stops. The cleanup function for the effect clears the interval to prevent memory leaks.
  • The start function sets isRunning to true, causing the stopwatch to start.
  • The stop function sets isRunning to false, causing the stopwatch to stop.
  • The reset function stops the stopwatch and resets the time to zero.
  • The stopwatch time is displayed in a mm:ss.SS format, where mm is minutes, ss is seconds, and SS is hundredths of a second.

The buttons for starting, stopping, and resetting the stopwatch are conditionally disabled based on whether the stopwatch is running.

In Node.js, the setTimeout function is used to schedule code execution after a designated amount of time. When you call setTimeout, it returns a Timeout object which represents the scheduled timeout. This object can be used to reference and control the timeout after it's been set.

In the context of TypeScript and the code example I provided, NodeJS.Timeout is the type definition that TypeScript uses for the value returned from setTimeout when using Node.js types. However, in a browser environment, which is typically the case with a React application, the returned value from setTimeout is a numerical ID, not a NodeJS.Timeout object. This is a discrepancy between Node.js and browser environments.

To correct the code example for a typical React environment (which runs in the browser, not in Node.js), you should use number as the type for the interval identifier. Here's how the corrected useEffect might look:

useEffect(() => {
let interval: ReturnType<typeof setInterval> | null = null;

if (isRunning) {
interval = setInterval(() => {
setTime((prevTime) => prevTime + 10);
}, 10);
} else if (!isRunning && time !== 0) {
clearInterval(interval!);
}

return () => interval && clearInterval(interval);
}, [isRunning, time]);

In this case, ReturnType<typeof setInterval> is used to infer the return type of setInterval. Since this code will be running in a browser, TypeScript will infer the return type as number, which is the correct type for the ID returned by setInterval in browser environments.