Formatting relative times with useNow
should sync "instantly" client side when component re-render
#1404
-
DescriptionAs explained in documentation here: https://next-intl-docs.vercel.app/docs/usage/dates-times#supplying-now The problem is that Verifications
Mandatory reproduction URLhttps://github.com/theoludwig/next-intl-bug-repro-relative-time-now Reproduction descriptionI've created a minimal reproduction using the template (https://github.com/amannn/next-intl-bug-repro-app-router), and only changed:
"use client"
import { useFormatter, useNow } from "next-intl"
import { useState } from "react"
interface Item {
name: string
createdAt: Date
}
const Demo: React.FC = () => {
const [items, setItems] = useState<Item[]>([])
const now = useNow({
updateInterval: 10_000,
})
const format = useFormatter()
return (
<main>
<button
onClick={() => {
setItems((oldItems) => {
return [
...oldItems,
{ name: `Item ${oldItems.length + 1}`, createdAt: new Date() },
]
})
}}
>
Add item
</button>
<ul>
{items.map((item) => {
return (
<li key={item.name}>
<span>{item.name}</span>
<span> - </span>
<span>Created {format.relativeTime(item.createdAt, now)}</span>
</li>
)
})}
</ul>
</main>
)
}
export default Demo Here each time we click on the button "Add item", we add a new item, and then display it, below in a list with the Then thanks to Expected behaviourThe relative time displayed should be correct "instantly" in the first render. What I'm suggesting is that |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Instead, for your case you can make this more explicit, e.g. creating a value const [now, setNow] = useState(useNow()); … and later updating it for every interaction that you find "worthy" of updating the time: <button
onClick={() => {
setNow(new Date())
// ... I'll move this to a discussion since this is a usage question. |
Beta Was this translation helpful? Give feedback.
now
refers to a global value that is shared across your whole application.updateInterval
can help to sync it periodically for a given call site, but according to the rules of React, the value is not updated just by a component re-rendering—a React component should always be ready to render.Instead, for your case you can make this more explicit, e.g. creating a value
now
based on the initial global value:… and later updating it for every interaction that you find "worthy" of updating the time:
I'll move this to a discussion since this is a usage question.