Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: SSR Combobox inner ref lost #7663

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

snowystinger
Copy link
Member

@snowystinger snowystinger commented Jan 24, 2025

Closes #7250

Added a SSR test which reproduces the bug. Haven't determined cause yet.

Best guess/working theory is that we let React render into the fake dom for collections. Usually, the last thing to render is the actual dom, so the ref is set correctly in that case. However, in this case, there appears to be an extra render in the fake dom, but not in the real dom, when I have a state change around the ComboBox.

I don't know how to verify this yet, nor how I could fix it if it were happening. At least, not without a custom renderer, which seems a bit heavy.
I attempted to remove the ref from everything in the CollectionBuilder/Document to no avail.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@nwidynski
Copy link
Contributor

nwidynski commented Jan 24, 2025

@snowystinger Took some time as well to look at this. My first intuition was also the fake DOM, but after noticing the issue being fixed by splicing the "non-collection" content from the builder, i was getting suspicious. Especially since only <ListBox /> content should have the required <Collection /> wrapper to even be hitting the fake DOM.

After additional investigation, it appears the issue is stemming from the switch in rendering strategies after initial hydration. The switch causes refs attached inside template to loose connection after moving to the portal. I tried assigning a stable key for both template and createPortal, but also to no avail.

The issue can only be fixed by maintaining a consistent strategy throughout the render cycle. (e.g. memoizing the useIsSSR() at hydration or by using template in both scenarios). I'm unsure whether this is possibly related to facebook/react#13563 or intended behavior.

In regards to the issuer objective, we currently calculate menuWidth with the rects of inputRef and buttonRef, so fixing this issue won't have impact on that. Unfortunately I can relate to the expectation of var(--trigger-width) to be dependent on triggerRef. Maybe we rename or even consider calculating based off triggerRef while clamping if smaller than input + button width as a courtesy. I feel like this could help avoid confusion moving forward 👍

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.

[RAC] Refs in collection components point to their "hidden" node after SSR
2 participants