Hello. Maybe it's possible add support Fragment for .createPortal method?
Example this code add wrapper for buttons
class FormButtons extends PureComponent {
constructor(props) {
super(props);
this.el = document.createElement('span');
// this.el = <Fragment />; // - it's the best solution without any wrappers
}
componentDidMount() {
const { portalSelector } = this.props;
document.getElementById(portalSelector).appendChild(this.el);
}
componentWillUnmount() {
const { portalSelector } = this.props;
document.getElementById(portalSelector).removeChild(this.el);
}
render() {
const { submit, reset, submitting, pristine } = this.props;
return ReactDOM.createPortal(
<Fragment>
<button
className="btn btn-primary btn-block"
type="submit"
onClick={submit}
disabled={submitting}
>
袟邪泻邪蟹邪褌褜
</button>
<button
className="btn btn-primary btn-block"
type="button"
onClick={reset}
disabled={submitting || pristine}
>
小斜褉芯褋懈褌褜
</button>
</Fragment>,
this.el
);
}
}
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
16.2
I don't understand this report. Is this a bug report, a feature request, or both combined?
Is using <Fragment>
inside ReactDOM.createPortal
not working for you? Can you create an isolated example?
Or is this a feature request about not having to create a target node? Then it's not clear how React could guess where to insert the items.
@gaearon This example https://codesandbox.io/s/j3qry8r38y
I see what createPortal receive as second argument the domNode. Why this domNode cannot be new Fragment?
PS Close this. I understand what it's impossible.
In React, there is a distinction between React elements and DOM elements.
Typically, your app is composed of React elements. However, they need to render into some DOM element. Typically you render your React <App />
into some DOM container, e.g. document.getElementById('root')
.
Portals let you render a React element subtree into a different DOM element. For example, you can render <Modal>
into document.getElementById('modal-container')
.
Your question is confusing me because the target can't be a React element. The point of portals is to render some React tree into a different DOM element. <Fragment>
is not a DOM element. It is a React element. You can't render "into" it, and thus it can't be a target of the portal.
However I would expect it to be possible to render a <Fragment>
into some DOM element, with or without a portal. I hope this makes sense!
@gaearon Hello. I solved this problem. I use as this.el = document.createDocumentFragment()
to .createPortal method with Fragment as parentNode. Your last sentence made me think about this thought
Nice! That should work yeah. But keep in mind React <Fragment>
is not the same as createDocumentFragment()
(in fact React <Fragment>
doesn't use DOM at all, which is why it works in React Native etc).
@romanlex I just want to comment that when using this.el = document.createDocumentFragment()
then document.body.removeChild(this.el)
would fail because this.el
was never attached to the body but only the child components.
Also wanted to mention that with DOM
fragments
I've run into the exception:
NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
That was happening when a portal was unmounting; No issues when using DOM
elements: this.el = document.createElement(...)
.
Most helpful comment
In React, there is a distinction between React elements and DOM elements.
Typically, your app is composed of React elements. However, they need to render into some DOM element. Typically you render your React
<App />
into some DOM container, e.g.document.getElementById('root')
.Portals let you render a React element subtree into a different DOM element. For example, you can render
<Modal>
intodocument.getElementById('modal-container')
.Your question is confusing me because the target can't be a React element. The point of portals is to render some React tree into a different DOM element.
<Fragment>
is not a DOM element. It is a React element. You can't render "into" it, and thus it can't be a target of the portal.However I would expect it to be possible to render a
<Fragment>
into some DOM element, with or without a portal. I hope this makes sense!