fix(web): match Astro's SSR useId prefix in manual island hydration - #803
Conversation
Astro's React renderer gives every server-rendered component an incrementing identifierPrefix (r0, r1, …) that React folds into each useId. A client:* island carries the prefix to the client on its astro-island wrapper, but our manual hydrateRoot mounts (client:* is banned repo-wide) passed no prefix — so every useId-bearing node (base-ui dropdown and tooltip triggers in ShellSidebar) mismatched and logged a hydration error on each signed-in page load. Recover the prefix from the server markup itself — every SSR'd useId embeds it as _<prefix>R_…_ — via a new detectIdentifierPrefix helper, and pass it to all four manual hydrateRoot call sites (both shell layouts, files tab, screenshots tab).
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (2)
🚫 Excluded labels (none allowed) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
uploads-web | e096e14 | Commit Preview URL Branch Preview URL |
Aug 23 2026, 05:22 PM |
Summary
Every signed-in page logged a React hydration mismatch from the
ShellSidebarisland (PR #800): server ids likebase-ui-_r1R_qq_vs clientbase-ui-_R_qq_on base-ui dropdown/tooltip triggers.Root cause: Astro's React renderer assigns each server-rendered component an incrementing
identifierPrefix(r0,r1, … — see@astrojs/react'sserver.js+context.js), which React folds into everyuseId. With aclient:*island the same prefix reaches the client on the<astro-island>wrapper, but our manualhydrateRootmounts (client:*is banned repo-wide) passed no prefix — client ids came out unprefixed and every useId-bearing node mismatched.Fix: the prefix is recoverable from the server markup itself, since every SSR'd useId embeds it as
_<prefix>R_…_. NewdetectIdentifierPrefixhelper inapps/web/src/lib/react-island.tsextracts it from the mount'sinnerHTML, and all four manualhydrateRootcall sites now pass it asidentifierPrefix:AccountLayout,AdminLayout, the files tab, and the screenshots tab (the latter two had the same latent bug for any useId-bearing content).Verification
pnpm --filter @uploads/web exec tsc --noEmitclean; web vitest suite 58 files / 871 tests pass/account/workspaces/dev-demo/people): before the fix every load logged the hydration error; after, an instrumented load showsidentifierPrefix=r1detected and the console is clean of hydration errors across repeated reloads