Stopwatch with State Management in LWC

Nikhil KarkraNikhil Karkra
2 min read

You will learn the following things

  • How to create a component

  • How to use setInterval

  • How to convert seconds to minutes and hours

  • How to use local storage

  • How to persist state

  • How to start, stop, and reset the watch

    Steps and Code:

    1. Create an LWC component named stopWatch

    2. In stopWatch.html, we create a card component that contains a heading, a timer, and a group of buttons.

    <!--stopwatch.html-->
    <template>
        <div class="slds-card slds-p-around_medium">
            <h2 class="slds-m-bottom_medium heading">Stop watch</h2>
            <div class="timer">{timer}</div>
            <div class="slds-p-around_medium">
                <lightning-button-group>
                    <lightning-button variant="success" label="Start" onclick={actionHandler}></lightning-button>
                    <lightning-button variant="destructive" label="Stop" onclick={actionHandler}></lightning-button>
                    <lightning-button variant="brand" label="Reset" onclick={actionHandler}></lightning-button>
                </lightning-button-group>
            </div>
        </div>
    </template>
  1. In stopWatch.js, we use the startTimerHandler method to generate the current date and time and store that timestamp in local storage with the key startTimer. The setTimer method is called when the start button is clicked. It checks if any time is already available in local storage and, if so, starts the timer, which updates every second. The secondToHms method converts seconds to hours and minutes, returning the time as a readable string. The connectedCallback method ensures that when the tab is changed and then revisited, the component checks whether the timer is running. If it is, it triggers the setTimer method.
    //stopwatch.js
    import { LightningElement } from 'lwc';

    export default class StopWatch extends LightningElement {

        timer = '0'
        timerRef

        actionHandler(event){
            const {label} = event.target
            if(label === 'Start'){
                this.setTimer()
            }
            if(label === 'Stop'){
                window.clearInterval(this.timerRef)
                window.localStorage.removeItem('startTimer')
            }
            if(label === 'Reset'){
                this.timer='0'
                window.clearInterval(this.timerRef)
                window.localStorage.removeItem('startTimer')
            }

        }
        StartTimerHandler(){
            const startTime = new Date()
            window.localStorage.setItem('startTimer', startTime)
            return startTime
        }
        setTimer(){
            const startTime = new Date( window.localStorage.getItem("startTimer") || this.StartTimerHandler())
            this.timerRef = window.setInterval(()=>{
                const secsDiff = new Date().getTime() - startTime.getTime()
                this.timer = this.secondToHms(Math.floor(secsDiff/1000))
            }, 1000)
        }

        secondToHms(d){
            d = Number(d)
            const h = Math.floor(d / 3600);
            const m = Math.floor(d % 3600 / 60);
            const s = Math.floor(d % 3600 % 60);
            const hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
            const mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
            const sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
            return hDisplay + mDisplay + sDisplay; 
        }

        connectedCallback(){
            if(window.localStorage.getItem("startTimer")){
                this.setTimer()
            }
        }
    }
  1. stopWatch.js-meta.xml

     <?xml version="1.0" encoding="UTF-8"?>
     <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
         <apiVersion>48.0</apiVersion>
         <isExposed>true</isExposed>
         <targets>
             <target>lightning__AppPage</target>
         </targets>
     </LightningComponentBundle>
    
  2. Create stopWatch.css file in the component folder and Add the following style to stopWatch.css file to styling.

     .heading{
         font-size: 30px;
         color: #295646;
         font-weight: 700;
     }
     .timer{
         font-size: 30px;
         padding:0 1rem;
     }
    

    Final Output

0
Subscribe to my newsletter

Read articles from Nikhil Karkra directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nikhil Karkra
Nikhil Karkra