Track elapsed time with lap support for productivity logging.
When building a precise stopwatch in JavaScript, you have two choices for getting the current time: Date.now() and performance.now(). Professional timing tools always use the latter.
Date.now() relies on the system clock. If your computer's clock syncs with an internet time server while the stopwatch is running, or if Daylight Saving Time occurs, Date.now() can jump backwards or forwards, completely ruining your stopwatch calculation.
performance.now() uses a Monotonic Clock. A monotonic clock is guaranteed to never go backwards and is entirely independent of the system's timezone or wall-clock time.
It represents the exact number of milliseconds that have passed since the web page was loaded (the navigation start time), often with sub-millisecond precision (e.g., 1045.234ms). By subtracting the performance.now() value at the moment the user clicks "Start" from the current performance.now() value, you get an ultra-precise elapsed time.
A common mistake when building a stopwatch in React is putting the current elapsed time in a standard state variable (useState) and updating it every 10 milliseconds.
React state updates trigger a re-render of the entire component tree. Forcing React to calculate virtual DOM diffs 100 times a second will cause massive CPU spikes, battery drain, and stuttering UI. High-performance stopwatches bypass React's render cycle by mutating a DOM element's textContent directly inside a requestAnimationFrame loop.
Why should you use performance.now() instead of Date.now() for measuring elapsed time?