Stopwatch is an application which helps to track time in hours, minutes, seconds, and milliseconds. This application implements all the basic operations of a stopwatch such as start, pause and reset button. It has an additional feature using which we can keep a record of laps which is useful when we have to note time for certain checkpoints.
Preview of Final Output:
Prerequisites and Technologies:
Approach:
This program creates a functional stopwatch timer with start, pause, reset, and lap features. It maintains state variables for hours, minutes, seconds, and milliseconds, ensuring real-time updates using the “useEffect” hook. Proper interval clearing prevents memory leaks, delivering a straightforward and reliable stopwatch for time tracking.
Functionalities:
- When users click “Start,” the timer begins, disabling the button with a “not-allowed” cursor.
- “Pause” stops the timer, and “Reset” sets all time units to zero.
- The program also offers a “Lap” feature for recording lap times, allowing users to track multiple intervals
Steps to create the application :
Step 1: Set up React project using the command
npx create-react-app <<name of project>>
Step 2: Navigate to the project folder using
cd <<Name_of_project>>
Step 3: Create a folder “components” and add three new files in it namely StopWatch.js, Lap.js and StopWatch.css.
Project Structure:
The updated dependencies in package.json will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
Example: Write the following code in respective files
- App.js: This file imports the StopWatch components and exports it.
- StopWatch.js: This file contains the logic to track time in hours, minutes, seconds, and milliseconds, offering user-friendly controls for starting, pausing, and resetting the timer.
- Lap.js : This file contains the logic for displaying the laps in a list. From StopWatch.js file we send a prop laps to this file.
- StopWatch.css: This file contains the design of the StopWatch.js elements.
Javascript
// App.js import './App.css' ; import StopWatch from './components/StopWatch' ; function App() { return ( <div className= "App" > <StopWatch /> </div> ); } export default App; |
Javascript
// StopWatch.js import React, { useState, useEffect } from "react" ; import "./StopWatch.css" ; import Lap from "./Lap" ; export default function StopWatch() { const [seconds, setSeconds] = useState(0); const [minutes, setMinutes] = useState(0); const [hours, setHours] = useState(0); const [miliSeconds, setMiliSeconds] = useState(0); const [laps, setLaps] = useState([]); const [isRunning, setIsRunning] = useState( false ); const formatWithLeadingZero = (number) => { if (number < 10) return "0" + number; else return number.toString(); }; useEffect(() => { let interval; if (isRunning) { interval = setInterval(() => { setMiliSeconds((miliSeconds) => { if (miliSeconds >= 99) { setSeconds((seconds) => { if (seconds >= 59) { setMinutes((minutes) => { if (minutes >= 59) { setHours((prevHours) => prevHours + 1); return 0; } else { return minutes + 1; } }); return 0; } else { return seconds + 1; } }); return 0; } else { return miliSeconds + 1; } }); }, 10); } return () => clearInterval(interval); }, [isRunning]); const handleStart = () => { setIsRunning( true ); }; const handlePause = () => { setIsRunning( false ); }; const handleLap = () => { const lapTime = formatWithLeadingZero(hours) + ":" + formatWithLeadingZero(minutes) + ":" + formatWithLeadingZero(seconds) + "." + formatWithLeadingZero(miliSeconds); setLaps((prevLaps) => [...prevLaps, lapTime]); }; const handleReset = () => { setIsRunning( false ); setMiliSeconds(0); setSeconds(0); setMinutes(0); setHours(0); setLaps([]); }; return ( <div className= "container" > <div className= "timeDisplay" > {formatWithLeadingZero(hours)} : {formatWithLeadingZero(minutes)} :{ " " } {formatWithLeadingZero(seconds)} : {formatWithLeadingZero(miliSeconds)} </div> <div className= "buttons" > <button className= "btn" onClick={handleStart} disabled={isRunning} style={{ cursor: isRunning ? "not-allowed" : "pointer" }} > Start </button> <button className= "btn" onClick={handlePause}> Pause </button> <button className= "btn" onClick={handleLap}> Lap </button> <button className= "btn" onClick={handleReset}> Reset </button> </div> <Lap laps={laps} /> </div> ); } |
Javascript
// Lap.js import React from "react" ; export default function Laps({ laps }) { const calculateTimeDifference = (timeString1, timeString2) => { const time1 = new Date(`1970-01-01T${timeString1}Z`); const time2 = new Date(`1970-01-01T${timeString2}Z`); const timeDiff = Math.abs(time2 - time1); const hours = Math.floor(timeDiff / 3600000).toString().padStart(2, '0' ); const minutes = Math.floor((timeDiff % 3600000) / 60000).toString().padStart(2, '0' ); const seconds = Math.floor((timeDiff % 60000) / 1000).toString().padStart(2, '0' ); const milliseconds = ((timeDiff % 1000) / 10).toString().padStart(2, '0' ); const resultString = `${hours}:${minutes}:${seconds}.${milliseconds}`; return resultString; } return ( <div className= "laps" style={{ display: (laps.length) ? 'block' : 'none' }}> <h3><span>Lap</span><span>Time</span><span>Total Time</span></h3> <ul> {laps.map((lap, index) => ( <li key={index}> <span>{`Lap ${index + 1}`}</span> <span>{calculateTimeDifference(lap, (index !== 0) ? laps[index - 1] : "00:00:00.00" )}</span> <span>{lap}</span> </li> ))} </ul> </div> ); }; |
CSS
/* StopWatch.css */ body { margin : 0 ; padding : 0 ; display : flex; justify- content : center ; align-items: center ; min-height : 100 vh; background-color : #f0f0f0 ; font-family : Arial , sans-serif ; } .container { padding : 30px ; border : 1px solid #ced4da ; border-radius: 10px ; background : #fff ; box-shadow: 0 0 6px rgba( 0 , 0 , 0 , 0.25 ); margin : 5px ; width : 100% ; max-width : 400px ; box-sizing: border-box; } .timeDisplay { padding : 20px ; font-size : 30px ; box-shadow: 0 0 6px rgba( 0 , 0 , 0 , 0.25 ); border-radius: 0.25em ; text-align : center ; } .buttons { display : flex; justify- content : center ; margin-top : 20px ; } button.btn { padding : 10px 20px ; outline : none ; border : 1px solid #ced4da ; margin : 5px ; border-radius: 4px ; cursor : pointer ; background : #1d9bf0 ; color : #fff ; font-size : 16px ; transition: all 0.5 s; } button.btn:hover { background-color : #1879ba ; } .laps { margin-top : 20px ; } .laps h 3 { text-align : left ; display : flex; justify- content : space-between; margin : 5px ; } .laps ul { list-style-type : none ; padding : 0 ; } .laps li { display : flex; justify- content : space-between; align-items: center ; margin : 0px 5px 10px 5px ; } @media screen and ( max-width : 420px ) { .buttons { display : grid; grid-template-columns: 1 fr 1 fr; } } |
Steps to run the application:
Step 1: Type the following command in terminal.
npm start
Step 2: Open web-browser and type the following URL
http://localhost:3000/
Output: