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 setsisRunning
totrue
, causing the stopwatch to start. - The
stop
function setsisRunning
tofalse
, causing the stopwatch to stop. - The
reset
function stops the stopwatch and resets thetime
to zero. - The stopwatch time is displayed in a
mm:ss.SS
format, wheremm
is minutes,ss
is seconds, andSS
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.