Repository navigation
fix: derive server useId values from tree position - #102
BleedingDev wants to merge 2 commits into
Conversation
Co-Authored-By: Claude Code <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 319d709 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
SSR frame and ID format packages/redact/src/dom/react-ids.ts, packages/redact/src/dom/root-internal.ts, packages/redact/src/server/dispatcher.ts |
The SSR frame now tracks tree and local IDs. useId formats identifiers from those values, and roots always set ri to true. |
Tree-slot traversal and suspended re-renders packages/redact/src/server/walk.ts, packages/redact/src/server/stream.ts |
The walker assigns tree IDs to child positions, sets and restores frame IDs during component rendering, and passes boundary tree IDs into re-renders. |
Hydration validation and SSR size allowances tests/ssr-tree-ids.test.tsx, tests/hydration.test.tsx, tests/mixed-renderer-hooks.test.tsx, scripts/compatibility-size-budget.mjs, scripts/size-check.mjs, tests/compatibility-size-budget.test.ts, .changeset/ssr-useid-tree-position.md |
Tests cover tree-position IDs across hydration and streaming cases. Size-check scripts add SSR-specific allowances, and a patch changeset records the update. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant Walk
participant Dispatcher
participant StreamBoundary
Walk->>Dispatcher: Set treeId and localId for component rendering
Dispatcher-->>Walk: Return useId value from treeId and localId
Walk->>StreamBoundary: Store treeId on suspended boundary
StreamBoundary->>Walk: Re-render boundary children with treeId
Possibly related PRs
- TanStack/redact#76: Changes client React ID assignment to use logical child slots, which PR
#102applies to SSR tree positions. - TanStack/redact#95: Introduces the compatibility size-allowance mechanism that PR
#102extends for SSR.
Suggested reviewers: tannerlinsley
Merge Risk: 
Minimal · up to 319d7
-
No concrete merge-blocking risk was found in the changed SSR ID and hydration paths.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Title check
-
Explanation
The title "fix: derive server useId values from tree position" matches the main change. The PR replaces the server render-order counter in the SSR dispatcher and walker with bigint tree positions, so server useId values follow React-style tree IDs. The title is short, specific, and states the primary change from the developer's view.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 7 functions across 11 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
⚔️ Resolve merge conflicts: 💡
-
- Resolve merge conflict in branch
fix/ssr-useid-tree-position
- Resolve merge conflict in branch
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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 @coderabbitai help to get the list of available commands.
|
Adding independent browser confirmation of the released bug and this proposed fix. This currently blocks our streamed-SSR adoption evaluation. To rule out application/configuration mistakes, we used a standalone complete HTML document with The tree has two suspended fields (A and B) separated by a synchronous parent/field. Fields use
The ready-ID control and a plain streamed-content control pass on both released runtimes and this PR. Separately, our unchanged generic Vite fixtures pass both default-prefix and explicit-prefix ID cases with this PR, after failing on the base. This supports attribution to Redact's runtime rather than our app or stream wrapper. It does not establish a surviving duplicate-ID defect: after recovery, the released runtime's final label controls work. We have not qualified a complete application, performance, or a combined/released version of these fixes. Environment: Linux, Bun 1.4.4, React/ReactDOM 19.3.1, Playwright 1.64.1, Chromium 156.0.8078.4, NODE_ENV=production. The published 0.2.2 tarball was integrity-checked; the source-built base and PR variants used the same build toolchain. |
Compare every hydrated descendant by reference so identical replacement markup cannot satisfy the adoption regression. Co-Authored-By: Claude Code <noreply@anthropic.com>
Why the change
Suspended server renders must produce the same useId values as hydration, without colliding with IDs allocated by later client mounts.
Special things to note
0c7274e.Change outline
Reproduction with
identifierPrefix: 'app-', whereSlowsuspends until after the shell has flushed:IDs in DOM order after reveal:
A separate prefix collision also occurs on main: the first server/hydrated field and a new client-only field can both receive
app-0; the new namespaces use_app-R_0_and_app-r_0_instead.On main,
packages/redact/src/server/dispatcher.ts:129-131uses a shared render-order counter, andpackages/redact/src/dom/dispatcher.ts:464-472lets an explicit prefix erase the server/client distinction.Added regressions in
tests/ssr-tree-ids.test.tsx:Existing literal-ID expectations change without removing DOM-identity assertions; a patch changeset accompanies the runtime change.
Sharing the leading-bit helper saves 2 source and 4 built gzip bytes compared with the original independent patch. The compatibility comparison permits only measured positive deltas against the exact base, including server min/gzip/Brotli growth and at most 48 bytes of client Brotli variation; other entries and metrics retain zero growth.
🤖 Generated with Claude Code
Summary by CodeRabbit