-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
What package within Headless UI are you using?
@headlessui/react
What version of that package are you using?
v2.2.1
What browser are you using?
Chrome
Reproduction URL
https://codesandbox.io/p/sandbox/bold-dawn-pnjkt8
In this example, you can toggle a div
that is rendered inside different portals (Headless UI, React, Floating UI, or without portal). The div
logs in its ref
callback if it is connected to the DOM, using the element.isConnected
property.
Describe your issue
The Headless UI Portal, when rendered the second time, renders the content before connecting it to the DOM.
How to reproduce:
- Open the CodeSandbox and the console to check the output
- Click on the button "Toggle Headless Portal"
✅ Console output:ref | isConnected true
- Click the button again to hide the portal.
- Click the button once more to show it again.
⚠️ Console output:ref | isConnected false

Expected Behavior:
On every render, the content should be connected to the DOM before the ref callback is invoked — just like it behaves when using:
• A standard div toggle
• A native React Portal
• A Floating UI Portal
You can use the other buttons in the CodeSandbox to see this behavior.
Actual Behavior
With Headless UI’s Portal, the initial render works as expected. But on subsequent renders, the ref is called before the content is connected to the DOM.
Real-World Impact
This behavior causes issues with React Hook Form, which filters out input elements that aren’t connected during initialization. Specifically:
• On the first open, a form inside a Headless UI dialog registers inputs correctly.
• On subsequent opens, radio inputs are no longer registered, because their ref is assigned before they’re connected to the DOM, and RHF filters them out.