Fix clientEntry collision for entries sharing an entry id#11524
Open
vismayIO wants to merge 2 commits into
Open
Fix clientEntry collision for entries sharing an entry id#11524vismayIO wants to merge 2 commits into
clientEntry collision for entries sharing an entry id#11524vismayIO wants to merge 2 commits into
Conversation
Two clientEntry() calls in the same file share an entry id (e.g. a bare import.meta.url), but are distinct components that must resolve to distinct exports. resolveClientEntries memoized resolution keyed by entry id, so the second entry adopted the first's resolution, producing the wrong client component and a hydration mismatch. Key the resolution cache by the component reference (the unique identity) instead of the entry id. Rendering the same component N times still hits the cache (one resolution per distinct component), while two components sharing an entry id now resolve independently. Fixes remix-run#11503 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
|
@markdalgleish and @ryanflorence, Could you please share any updates on this PR? Also, let me know if there’s anything else I can do to help resolve the issue. |
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.
Problem
Fixes #11503
Two
clientEntry(import.meta.url, namedFn)exports declared in the same file and rendered in the same SSR pass both hydrate as the first one. The server renders each correctly, but on hydration the second's slot adopts the first component, causing a hydration mismatch and the wrong interactive component on the client.resolveClientEntriesmemoized resolution in aMapkeyed byentryIdonly (packages/ui/src/server/stream.ts). A bareimport.meta.urlmakesentryIdthe file, so twoclientEntriesin one file share it: the hook runs once (with the first component) and the second instance reuses that result; the second'scomponent.nameis never looked at. Both entries streamexportName: "Alpha".Fix
Key the resolution cache by the component reference (the unique identity) instead of the
entryIdstring:entryId→ different references → resolved independently with their ownexportName.Client-side hydration was already correct (keyed per unique instance id); the corruption was purely in SSR resolution.
Tests
resolves two clientEntries sharing one entry id to distinct exports during SSR— fails before the fix (both resolve toAlpha), passes after.calls resolveClientEntry only once per unique entry id during SSRstill passes (same component rendered 3× → one resolve call).@remix-run/uisuite: 792 pass, 0 fail.