Repository navigation
fix(ui): render relative times stably through hydration - #5058
Merged
Merged
Conversation
A page rendered and cached on the server is hydrated later, under the
viewer's clock. A relative time ("3d ago") computed during render can then
differ from the server HTML across a unit boundary, which throws React
error 418 and discards the server render.
Add RelativeTime: it renders the UTC date on the server and during
hydration, then the relative text. Host-worded text passes through as
children, with an optional stable twin. ChangeLine, the overview hotspot
and activity rows, and the other render-time relative times use it.
RelativeTime took host-computed text as children. Under a server
component that text is computed once on the server, so after hydration
the page showed an age frozen at render or cache time.
RelativeTime now always measures the age itself, from the viewer's clock.
Hosts word it with plain strings that cross the client boundary: a
template with a {time} placeholder, per-bucket words with a {value}
placeholder (formatRelativeTime takes the same map), and a fallback for a
missing or future date. ChangeLineCopy.relativeTime becomes ago words, and
packages/web builds them from overview.ago.*. The time renders in a
<time> element titled with the full UTC date-time.
swati510
approved these changes
Oct 31, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Relative times ("3d ago", "Since the previous index, 2d ago") rendered on the server could differ from the text the browser computes during hydration. That raised a React text-mismatch error, and React threw away the server HTML.
How
RelativeTimecomponent inpackages/ui/src/shared. On the server and during hydration it renders a fixed UTC date. After hydration it renders the age from the viewer's clock, inside a<time dateTime title>element.template(with{time}),words(per-unit wording with{value}) andfallback. Server components can therefore localise the text without freezing the age at render time.formatRelativeTimeaccepts the same optional words map. English output is unchanged.ChangeLineCopy.relativeTimeis replaced byago(per-unit words); the web overview copy builds it from its i18n messages.formatIndexedAtand uses the shared formatter.Verification
tsc --noEmit: clean.