I bumped into this problem when working on a side project - aihairstyles.com. When users generate a new set of styles, I want to show them when that set was generated, relative to now. I also want that time to update dynamically as time goes on, without the need for them to refresh the page. Finally, I want to use this logic throughout my app in lots of places.
I solved it with a combination of global state, date-fns library and a small plugin I wrote.
1. Create a state variable to hold a "ticker"
In my useState.ts
file, I'm adding a variable that we'll update later via a plugin.
export const useTicker = () => useState<any>('ticker', () => new Date().getTime())
2. Create a plugin to update this ticker at a given interval
// globalTicker.client.ts
export default defineNuxtPlugin(nuxtApp => {
// updating a global ticker in useState that can be used to auto-update times in the UI
const ticker = useTicker()
const TICKER_INTERVAL = 30000; // milliseconds
setInterval(() => {
let newVal = new Date().getTime();
ticker.value = newVal
}, TICKER_INTERVAL);
})
With this plugin, every 30 seconds the ticker will update (30000 milliseconds).
3. Install date-fns library (or a lib of your choosing)
I used to use moment.js, but date-fns is my go-to now as it's smaller and can be tree-shaken. But use whatever makes you happy.
npm install date-fns --save
4. Create a composable that exports a relative time function
As I mentioned, I wanted this logic throughout my app in lots of places, so creating a composable was the way to go.
To do this, I created a file called useDateHelpers.ts
in my /composables
directory.
// /composables/useDateHelpers.ts
import formatDistance from 'date-fns/formatDistance'
export const relativeDate = (date:string) => {
console.log("date:", date)
const ticker = useTicker()
return formatDistance(new Date(date), ticker.value)
}
Notice we're importing our global ticker and using it, making our function's return value reactive in Vue's eyes.
5. Finally, use the function in our components
Then, in the html, we use this function and pass in the created_date and the global ticker variable. In the code below we have a for-loop that loops over all image sets.
<!-- rest of preview page ) -->
<h2 class="gradient-text-1 text-2xl">
{{preview.data.style}}
</h2>
<p class="text-sm muted mb-3">
{{ relativeDate(preview.data.result_data?.created_at)}} ago
</p>
<!-- rest of preview page -->
The result? We have relative time updating in our UI.
I think it works quite well.
Any suggestions for improvement? Let me know :)
Also, I'm actively building aihairstyles.com, would love feedback on that too 🙏🏼.
Chris
Top comments (0)