Vue Timer Hook
Vue Timer Hook is a Vue 3 composition API library providing reactive hooks for common time-based functionalities within components. It offers `useTimer` for countdowns, `useStopwatch` for tracking elapsed time, and `useTime` for continuously retrieving the current time. Currently at version 1.0.86, the library demonstrates a positive version release cadence, with the last publish occurring 3 months ago, indicating active maintenance. Its primary benefit lies in simplifying time-related state management in Vue components, abstracting away complex `setInterval` and `clearInterval` logic, and providing a clean, reactive interface. It is purpose-built for the Vue 3 ecosystem and the Composition API, making it a direct fit for modern Vue projects.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'value')
cause Attempting to access a reactive property (e.g., `isRunning`, `isExpired`, `seconds`) from a `vue-timer-hook` return value without appending `.value`.fixAccess reactive properties using `.value`, for instance: `timer.isRunning.value` or `timer.seconds.value`. -
Syntax Error: [plugin:vite:vue] `useTimer` is not defined
cause The component where the hook is used is not set up for Vue 3 Composition API (e.g., missing `<script setup>`), or the project is using Vue 2.fixEnsure your Vue component uses `<script setup lang='ts'>` and your project is configured for Vue 3. -
Uncaught TypeError: time.setSeconds is not a function
cause The `expiryTimestamp` argument provided to `useTimer` is not a valid JavaScript `Date` object or a numeric timestamp.fixEnsure `useTimer` is initialized with a properly constructed `new Date()` object, for example: `const time = new Date(); time.setSeconds(time.getSeconds() + 300);`.
Warnings
- breaking `vue-timer-hook` is exclusively designed for Vue 3's Composition API. It is not compatible with Vue 2 or the Options API without significant adaptation, and attempting to use it will lead to runtime errors due to missing Vue 3 specific APIs.
- gotcha When accessing reactive state properties like `timer.isExpired`, `stopwatch.isRunning`, or any time value (e.g., `timer.seconds`), remember they are Vue `ref` objects and require `.value` to access their current primitive state (e.g., `timer.isExpired.value`, `timer.seconds.value`). Direct access without `.value` will return the ref object itself, potentially leading to incorrect logic or rendering issues.
- gotcha The `expiryTimestamp` parameter for `useTimer` expects a JavaScript `Date` object or a numeric timestamp (milliseconds since epoch). Providing other types (e.g., a plain number for seconds) or an invalid `Date` object will result in the timer behaving unexpectedly or not starting at all.
- gotcha The `restart` method for `useTimer` requires a *new* `Date` object to define the new expiry timestamp. Reusing and mutating the *same* `Date` object reference passed initially might not trigger reactivity as expected; always create a fresh `Date` for subsequent `restart` calls.
- gotcha When conditionally rendering components that use `vue-timer-hook` (e.g., with `v-if`), Vue might reuse component instances without re-running setup logic if a `key` attribute is not provided, leading to timers not initializing or resetting correctly.
Install
-
npm install vue-timer-hook -
yarn add vue-timer-hook -
pnpm add vue-timer-hook
Imports
- useTimer
const useTimer = require('vue-timer-hook')import { useTimer } from 'vue-timer-hook' - useStopwatch
import useStopwatch from 'vue-timer-hook'
import { useStopwatch } from 'vue-timer-hook' - useTime
import { useTime } from './vue-timer-hook'import { useTime } from 'vue-timer-hook'
Quickstart
<template>
<div>
<h1>Vue Timer Hook Demo</h1>
<p>Countdown Timer:</p>
<div>
<span>{{ timer.days }}</span>:<span>{{ timer.hours }}</span>:<span>{{ timer.minutes }}</span>:<span>{{ timer.seconds }}</span>
</div>
<p>{{ timer.isRunning.value ? 'Running' : 'Not running' }}</p>
<button @click="timer.start()">Start</button>
<button @click="timer.pause()">Pause</button>
<button @click="timer.resume()">Resume</button>
<button @click="restartFive()">Restart to 5 minutes</button>
</div>
</template>
<script setup lang="ts">
import { watchEffect, onMounted, ref } from 'vue'
import { useTimer } from 'vue-timer-hook'
// Set an initial 10-minute timer
const initialTime = new Date()
initialTime.setSeconds(initialTime.getSeconds() + 600) // 10 minutes
const timer = useTimer(initialTime, { autoStart: true })
const restartFive = () => {
// Restarts to a new 5-minute timer
const newTime = new Date()
newTime.setSeconds(newTime.getSeconds() + 300)
timer.restart(newTime)
}
onMounted(() => {
// Watch for the timer to expire
watchEffect(() => {
if (timer.isExpired.value) {
console.log('Timer has expired!')
// You could trigger an action here, e.g., show a message
}
})
})
</script>