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

Make sure as={Fragment} doesn’t result in a render loop #2760

Merged
merged 4 commits into from Sep 20, 2023

Conversation

thecrypticace
Copy link
Contributor

In Headless UI we have to merge multiple refs when rendering. For example we might use a ref internally to get access to a DOM node and the user might also pass in their own ref via forwardRef.

Our render() has to do some work to merge refs of children when rendering Fragment components. However, the ref callback we created was not stable. This resulted in an infinite render loop in certain scenarios where rendering a child component causes the parent to re-render (because of shared state in a context for instance).

A side-effect of this render loop was that <Suspense> did not work as expected. Sometimes never updating until the suspense boundary was re-created.

This introduces a new, internal hook called useMergeRefsFn that we can use that allows us to merge multiple refs and while always producing a stable callback for React so it knows not to trigger a re-render.

Fixes #2757

@vercel
Copy link

vercel bot commented Sep 19, 2023

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 19, 2023 8:59pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 19, 2023 8:59pm

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.

Lazy-loaded components do not show inside disclosure panel the first time it is opened
1 participant