Web worker inside react component causing race condition

I am trying to create a performant timer component in React.js (for learning purposes) and for that I am using web workers. The logic works as expected the first time when I click “Start” button but some weird race like condition starts appearing in countdown when I stop the counter and start again and then stop, only this time it won’t stop and timer speed accelerates!

Live code at: https://stackblitz.com/edit/timer-worker-wfs7e3

Trying to explain the process step by step:

Step Action Button State Timer State Note
1 Clicks “Start” Text updates to “Stop”. Color to “red” Active Timer starts as expected with speed as expected
2 Clicks “Stop” Text updates to “Start”. Color to “blue” Inactive Timer resets as expected
3 Clicks “Start” Text updates to “Stop”. Color to “red” Active Timer starts as expected with speed as expected
4 Clicks “Stop” Text updates to “Start”. Color to “blue” Active! Timer resets to 0 but doesn’t stop and starts running slightly faster
5 Clicks “Start” Text updates to “Stop”. Color to “red” Active! Timer resets to 0 but doesn’t stop and starts running even more faster

And so on. This keeps on happening until I refresh my page.
By the looks of it, seems that that there’s some race condition going on ( I maybe wrong) And I am unable to figure out the root cause. Is it bug or simply a failure at logical level?

// /src/workers/timer-worker.ts
const timerWorker = () => {
  let seconds = 0
  let timerId: number | null = null

  const INTERVAL = 100

  function dataFactory(time: number, status: "start" | "stop") {
    return { time, status }
  }

  self.onmessage = (event) => {
    if (event.data === "start") {
      seconds = 0
      timerId = setInterval(() => {
        seconds++
        self.postMessage(dataFactory(seconds, "start"))
      }, INTERVAL)
    }

    if (event.data === "stop") {
      seconds = 0
      self.postMessage(dataFactory(seconds, "stop"))
      clearInterval(timerId as number)
    }
  }
}

export default timerWorker
// /src/workers/web-worker.ts
export default class WebWorker {
    constructor(worker: any) {
        const code = worker.toString();
        const blob = new Blob(['('+code+')()']);
        return new Worker(URL.createObjectURL(blob));
    }
}

// src/components/Timer.tsx
import { FC, useEffect, useRef, useMemo, useState } from "react"
import { Timer as TimerStatus } from "../enums/timer"
import TimerWorker from "../worker/timer-worker"
import WebWorker from "../worker/web-worker"

export interface TimerProps {}

const Timer: FC<TimerProps> = () => {
  const [timerRunning, setTimerRunning] = useState(false)
  const [seconds, setSeconds] = useState(0)
  const workerRef = useRef<Worker | null>(null)

  const timer = useMemo(() => {
    const secs = seconds % 60
    const mins = Math.floor(seconds / 60) % 60
    const hrs = Math.floor(seconds / 3600) % 24
    const days = Math.floor(seconds / (3600 * 24))

    return `${days}d ${hrs}h ${mins}m ${secs}s`
  }, [seconds])

  const btnStyle = `btn ${timerRunning ? "btn-danger" : ""}`

  function initTimerWorker() {
    workerRef.current = new WebWorker(TimerWorker)
    workerRef.current.onmessage = (event) => {
      console.log(event.data)
      const { time, status } = event.data
      console.log(time, status)
      setSeconds(time)
    }

    // useEffect cleanup
    return () => workerRef.current?.terminate()
  }

  function clickHandler() {
    setTimerRunning((prev) => {
      const newState = !prev
      workerRef.current?.postMessage(
        newState ? TimerStatus.START : TimerStatus.STOP
      )
      return newState
    })
  }

  useEffect(initTimerWorker, [])

  return (
    <div
      id="Timer"
      className="place-self-center bg-white rounded-md p-4 w-80 text-center border border-solid border-slate-200"
    >
      <div className="text-3xl mb-2 font-bold">{timer}</div>
      <button className={btnStyle} onClick={clickHandler}>
        {timerRunning ? "Stop" : "Start"}
      </button>
    </div>
  )
}

export default Timer
// /src/enums/timer.ts

export enum Timer {
    START = "start",
    STOP = "stop"
}

Live code at: https://stackblitz.com/edit/timer-worker-wfs7e3