-
Notifications
You must be signed in to change notification settings - Fork 46.5k
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
RFC: Context scoping for compound components #23287
Comments
Could you allow a context to be passed in as an optional prop to Dialog.Root? i.e. the AlertDialog primitives create their own context for Dialog and pass it in as a prop to Dialog.Root and any other Dialog primitive that may need it: |
That's what we're doing:
But doesn't solve it consumer-side 😢 we can suggest consumers do the same if we package our solution but given composition is such a fundamental part of React, it feels like something that should be easier to achieve. |
This isn't a solution, but perhaps of interest, Jotai has a concept of 'scope' that is passed to the https://jotai.org/docs/api/core#type-script |
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! |
bump |
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! |
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you! |
The problem
Our Radix Primitives API is intentionally very open allowing for all sorts of compositions. For example:
An issue arises here though...
The
AlertDialog
is aDialog
composition under the hood with additional functionality bound to meetAlertDialog
requirements. Therefore,AlertDialog.Root
is also aDialog.Root
so provides bothDialogContext
andAlertDialogContext
.Due to the way React Context works, the composition above means the
AlertDialog.Trigger
(also aDialog.Trigger
) woulduseContext(DialogContext)
and retrieve the context fromDialog.Root
instead ofAlertDialog.Root
. Clicking theAlertDialog.Trigger
would toggle theDialog.Content
.An initial solution might be to create hooks containing all
Dialog
functionality so that we can create a new context for each component type and bind dialog functionality using hook. However, if consumers create their ownDialog
compositions from ours the problem still exists, it's just moved:Instead of using hooks, we currently solve this internally by creating a new context that
AlertDialog
passes to its internalDialog
via a__scope
prop, whichDialog
then passes to all of itsuseContext
calls. Unfortunately, this still doesn't solve the consumer side issue mentioned above.This also sounds a lot simpler than the actual implementation ended up being because an
AlertDialog
can be recomposed which has its own multiple parts as well as dialog parts. Therefore,__scope
is a mapping of contexts e.g:The Proposal
A way to scope a component's context when re-composing it to ensure
AlertDialog
parts don't accidentally retrieve context from another component composed of similar parts.Given composition is a big part of React, it seems this would be really useful if it were handled by React somehow. Perhaps it already is and there is a simpler way we can achieve this with a different approach?
We have had someone request that we expose our scoping solution as an npm package (which we can but it needs refining before we could do that) so it seems others are facing these issues.
"Just re-order parts"
We could make sure all
AlertDialog
parts are insideDialog
to avoid this but a more real-world use-case where re-ordering parts is not always possible or obvious where they should go would be aDropdownMenu
andTooltip
that both use aPopper
under the hood, so both referencePopperContext
:The popper rendered by
DropdownMenuContent
cannotgetBoundingClientRect
for itstriggerRef
because the ref is attached to theTooltip
sPopperContext
.The text was updated successfully, but these errors were encountered: