-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 closing components using the transition
prop, and after scrolling the page
#3407
Merged
Conversation
This file contains 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
This change should be temporary, and it will allow us to use the `useDidElementMove` with ref objects and direct `HTMLElement`s.
This change should be temporary, and it will allow us to use the `useResolveButtonType` hook with ref objects and direct `HTMLElement`s.
This change should be temporary, and it will allow us to use the `useRefocusableInput` hook with ref objects and direct `HTMLElement`s.
Accept `HTMLElement| null` instead of `MutableRefObject<HTMLElement | null>` in the `useTransition` hook.
So far we've been tracking the `button` and the the `items` DOM nodes in a ref. Typically, this is the way you do it, you keep track of it in a ref, later you can access it in a `useEffect` or similar by accessing the `ref.current`. There are some problems with this. There are places where we require the DOM element during render (for example when picking out the `.id` from the DOM node directly). Another issue is that we want to re-run some `useEffect`'s whenever the underlying DOM node changes. We currently work around that, but storing it directly in state would solve these issues because the component will re-render and we will have access to the new DOM node.
This doesn't support the `MutableRefObject<HTMLElement | null>` anymore.
We don't handle `MutableRefObject<HTMLElement | null>` anymore
Only accept `HTMLElement | null` instead of `MutableRefObject<HTMLElement | null>`
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
RobinMalfait
commented
Aug 1, 2024
RobinMalfait
changed the title
Fix closing components in combination with the
Fix closing components using the Aug 2, 2024
transition
prop, and after scrolling the pagetransition
prop, and after scrolling the page
This was referenced Sep 18, 2024
This was referenced Sep 20, 2024
This was referenced Sep 23, 2024
This was referenced Sep 25, 2024
This was referenced Sep 26, 2024
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.
This PR fixes an issue where components such as the
MenuItems
and theListboxOptions
won't close correctly if these are used in combination with thetransition
prop and after you scrolled the page a little bit.For some background information: the
Menu
andListbox
components can be used with thetransition
prop so that theMenuItems
andListboxOptions
can be transitioned in and out based on the open/closed state.To make the user experience better, we have some logic to check whether the
MenuButton
orListboxButton
moved from its initial position. If it did move when it's closing, then we immediately stop all transitions by unmounting theMenuItems
orListboxOptions
immediately.A situation this happens in:
Menu
(with thetransition
prop)MenuItems
will fade out while moving around (while the page scrolls)anchor
prop, then theMenuItems
will reposition itself which makes the UX even worse.While debugging this issue, I noticed a timing related issue because we are using the DOM element in a
useTransition
hook. Typically you store those DOM elements in auseRef
. This is good practice because the DOM element will be filled in once you hit theuseEffect
hook, and you don't introduce unnecessary re-renders.However, if the DOM element changes, then the
useRef
value will update, but theuseEffect
hook doesn't run again (because no state change happened).There are other places in Headless UI where we also need to re-run effects when the DOM node changes. There are also places where we need access to the DOM element during render.
One of React's rules is to not read / write a ref during render.
So, this PR simplifies a few components and hooks by actually storing the DOM elements in state directly instead of in a ref. This way we can use the DOM element in dependency arrays of
useEffect
hooks, and we can use the DOM element during render.Maybe a bit of an unorthodox solution, but it works quite well and it simplifies the code quite a bit.
It might be easier to review commit by commit. The reason why is that in some hooks I added temporary support for
HTMLElement | null
in places where we wantedMutableRefObject<HTMLElement | null>
. These now temporary look likeMutableRefObject<HTMLElement | null> | HTMLElement | null
.This way we can use both versions while refactoring. By the end of the commits those are simplified again such that we only handle
HTMLElement | null
instead ofMutableRefObject<HTMLElement | null>
.Fixes: #3398
Fixes: #3403