Last active
February 19, 2026 13:15
-
-
Save meduzen/6ee1cd0d8a3ce589862801e9ddfb4ce9 to your computer and use it in GitHub Desktop.
Approach for an updated current datetime (“now”) in a vue-x store (Vue 2/3) or a Pinia store (Vue 3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const MILLISECONDS_PER_MINUTES = 1000 * 60; | |
| const state = { | |
| now: (new Date()), | |
| intervalTimer: null, | |
| }; | |
| const mutations = { | |
| now(state) { | |
| state.now = new Date(); | |
| }, | |
| setIntervalTimer(state, callback) { | |
| state.intervalTimer = setInterval(() => { | |
| if (callback) { | |
| callback(); | |
| } | |
| }, MILLISECONDS_PER_MINUTES * 3); | |
| }, | |
| clearIntervalTimer(state) { | |
| if (state.intervalTimer) { | |
| clearInterval(state.intervalTimer); | |
| state.intervalTimer = null | |
| } | |
| } | |
| }; | |
| const actions = { | |
| pollNow({ commit, state }) { | |
| if (!state.intervalTimer) { | |
| commit("setIntervalTimer", () => commit("now")); | |
| } | |
| }, | |
| clearPollNow({ commit }) { | |
| commit("clearIntervalTimer"); | |
| }, | |
| }; | |
| const time = { | |
| namespaced: true, | |
| state, | |
| mutations, | |
| actions, | |
| }; | |
| export default time; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { onBeforeMount, onUnmounted, ref } from 'vue' | |
| const REFRESH_INTERVAL_MS = 1000 | |
| let timer | |
| let subscribers = 0 | |
| /** Current date and time, updated every second. */ | |
| const now = ref(new Date()) | |
| const poll = () => { | |
| if (!timer) { | |
| timer = setInterval(() => { | |
| now.value = new Date() | |
| }, REFRESH_INTERVAL_MS) | |
| } | |
| } | |
| const stopPoll = () => { | |
| if (timer) { | |
| clearInterval(timer) | |
| timer = null | |
| } | |
| } | |
| /** | |
| * Subscribe to the polling of the current date and time. | |
| * Once subscribed, `now` is periodically updated. | |
| */ | |
| const subscribe = () => { | |
| if (!subscribers++) { | |
| poll() | |
| } | |
| } | |
| /** | |
| * Unsubscribe of the polling of the current date and time. | |
| * Once unsubscribed, `now` may stop to be updated. | |
| */ | |
| const unsubscribe = () => { | |
| subscribers-- | |
| if (!subscribers) { | |
| stopPoll() | |
| } | |
| } | |
| /** | |
| * Current date, updated every second. | |
| * | |
| * It start to update automatically on the first component to be mounted, and | |
| * stop updating on the last unmounted one. For non-component usages, use | |
| * `useNowSubscription`. | |
| */ | |
| export const useNow = () => { | |
| onBeforeMount(subscribe) | |
| onUnmounted(unsubscribe) | |
| return { now } | |
| } | |
| /** | |
| * Current date, updated every second. | |
| * | |
| * It requires manual (de)activation using (un)subscribe methods. Suitable in a | |
| * non-component environment (like a store). For components, use `useNow`. | |
| */ | |
| export const useNowSubscription = { subscribe, unsubscribe, now } |
Author
Hi @meduzen, this is really awesome! I was having a bit of trouble implementing something like this myself and your solution helped me out! 😄
Author
Hey, thanks for the feedback @cjbeattie! I forgot I made this gist. 😅
Author
Just added a useNow composable, suitable for Vue 3 composition API.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What this store module does
It provides action that can start/stop a polling (
setInterval) updating the current time (state.now) every 3 minutes.Approach
I put both the
setIntervalandclearIntervalcalls in mutations because they are mutatingstate.intervalTimer.setIntervalis having a callback mutating another part (state.now), but the decision to mutate another property is driven in an action (pollNow).I would love feedback on this approach.