tailwindlabs / headlessui

Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
https://headlessui.com
MIT License
25.81k stars 1.07k forks source link

Fix crash when using `DisclosureButton` inside of a `DisclosurePanel` when the `Disclosure` is open by default #3465

Closed RobinMalfait closed 3 weeks ago

RobinMalfait commented 3 weeks ago

This PR fixes an issue where React hooks were called unconditionally>

The PopoverButton and DisclosureButton act as a CloseButton when used inside of a panel. We conditionally handled the ref when it's inside a panel. To ensure that the callback is stable, the conditionally used function was wrapped in a useEvent(…) hook.

This seemed to be ok (even though we break the rules of hooks) because a button can only be in a panel or not be in a panel, but it can't switch during the lifetime of the button. Aka, the rules of hooks are not broken because all code paths lead to the same hooks being called.

<Disclosure defaultOpen>
  <DisclosureButton>Open</DisclosureButton>
  <DisclosurePanel>
    <DisclosureButton>Close</DisclosureButton>
  </DisclosurePanel>
<Disclosure>

But... it can be called conditionally, because the way we know whether we are in a panel relies on a state value which comes from context and is populated by a useEffect(…) hook.

The reason we didn't catch this in the Disclosure component, is because all the state is stable and known by the time the DisclosurePanel opens. But if you use the defaultOpen prop, the DisclosurePanel is already open and then the state is not ready yet (because we have to wait for the useEffect(…) hook).

Long story short, moved the isWithinPanel check inside the useEvent(…) hook that holds the stable function which means that we don't call this hook unconditionally anymore.

vercel[bot] commented 3 weeks ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 9, 2024 7:12pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 9, 2024 7:12pm