RFC: Portal improvements
See original GitHub issueI’m using this issue to collect my thoughts on refactors and fixes for the Portal. I’ll continue adding to this as I find things I’d like to change.
Callbacks
-
#901 onOpen/onClose do not fire when they shouldTurned out to be invalid. -
#1280 Theopen
prop in thedata
param to callbacks should be the proposedopen
value, not the current value. This way, it can be used in anonOpen => open
loop for a controlled component. Identical to theonChange => value
loop for an input, checkbox, etc. The value is the would-be-value should the update take effect, not the current controlled value.
Timeouts
-
open/closeWithTimeout
should not use a timeout when there is!delay
or it is0
. This causes the Portal to wait an unnecessary tick before setting state.
Too many nodes (mountNode, rootNode, portalNode)
Name | Definition |
---|---|
mountNode |
Where the portal should be rendered (similar to React.render(_, mountNode) ) |
rootNode |
Portal’s own root div , child of mountNode |
portalNode |
Portal’s child, which is rendered into the Portal’s rootNode |
Kill rootNode
I realize a naive implementation would not work as it would replace document.body
by default. However, I still think we should consider a more robust path to rendering the Portal child directly to the DOM rather than wrapper in a rootNode
. Why? I’ve got at least 3 reasons.
Reason 1 - Unintuitive
I think the intuition is that if I “portal” a span
to the document.body
, then the DOM would look like so:
<Portal mountNode={document.body}>
<span />
</Portal>
<body>
<span></span>
</body>
When in fact it looks like this:
<body> <!-- mountNode={document.body} -->
<div> <!-- rootNode (Portal's root) -->
<span></span> <!-- portalNode (Portal's child) -->
</div>
</body>
Reason 2 - rootNode
is not a component
There is also the fact that the rootNode
is not a React component, it is a DOM node. This means it doesn’t accept props (currently handles className with DOM APIs). This makes it impossible to put say an inline style or event handler on it.
Reason 2 - One more enforced wrapper to deal with
This only further exacerbates issues related to CSS and layout, since, there is no way to get your component to be a direct child of the body
. It is always wrapped in a div. Ideally, you could portal your component to the
body` and have it be a direct child.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:3
- Comments:8 (4 by maintainers)
IMHO, splitting logic and behavior should be done with care and only out of absolute necessity. It gets very difficult to test splits. Also, having an app do one thing for some users and an entirely different thing for other users creates a lot of confusion and extra difficulty fielding issues.
I’d rather stay with our Portal until it makes sense to abandon React 15 support. Then, make a clean swap at that time.
There has been no activity in this thread for 180 days. While we care about every issue and we’d love to see this fixed, the core team’s time is limited so we have to focus our attention on the issues that are most pressing. Therefore, we will likely not be able to get to this one.
However, PRs for this issue will of course be accepted and welcome!
If there is no more activity in the next 180 days, this issue will be closed automatically for housekeeping. To prevent this, simply leave a reply here. Thanks!