Skip to content

fix(web): match Astro's SSR useId prefix in manual island hydration - #803

Merged
Zach Dunn (zachdunn) merged 1 commit into
mainfrom
fix/manual-island-useid-prefix
Aug 23, 2026
Merged

fix(web): match Astro's SSR useId prefix in manual island hydration#803
Zach Dunn (zachdunn) merged 1 commit into
mainfrom
fix/manual-island-useid-prefix

Conversation

@zachdunn

Copy link
Copy Markdown
Member

Summary

Every signed-in page logged a React hydration mismatch from the ShellSidebar island (PR #800): server ids like base-ui-_r1R_qq_ vs client base-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's server.js + context.js), which React folds into every useId. With a client:* island the same prefix reaches the client on the <astro-island> wrapper, but our manual hydrateRoot mounts (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_…_. New detectIdentifierPrefix helper in apps/web/src/lib/react-island.ts extracts it from the mount's innerHTML, and all four manual hydrateRoot call sites now pass it as identifierPrefix: AccountLayout, AdminLayout, the files tab, and the screenshots tab (the latter two had the same latent bug for any useId-bearing content).

Verification

  • Unit tests for the helper (prefix extraction, H-suffixed variant, client-format ids don't match)
  • pnpm --filter @uploads/web exec tsc --noEmit clean; web vitest suite 58 files / 871 tests pass
  • Live on the local stack (signed-in dev-session, /account/workspaces/dev-demo/people): before the fix every load logged the hydration error; after, an instrumented load shows identifierPrefix=r1 detected and the console is clean of hydration errors across repeated reloads

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).
@changeset-bot

changeset-bot Bot commented Aug 23, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: e096e14

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (2)
  • coderabbit:review
  • review
🚫 Excluded labels (none allowed) (1)
  • wip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ac5db9c2-405a-4985-85d6-d91357b4202c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

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

@zachdunn
Zach Dunn (zachdunn) merged commit 469c35a into main Aug 23, 2026
4 checks passed
@zachdunn
Zach Dunn (zachdunn) deleted the fix/manual-island-useid-prefix branch August 23, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant