I understand that it's probably a bad idea to ReactDOM.render()
into document.body
. But are there any issues with using ReactDOM.createPortal()
with document.body
?
Tried looking for examples of React going bonkers when you render into body so I could test it out with createPortal but I wasn't able to find any.
To put things into context, here's a sample usage I'm speaking about:
import React from 'react';
import ReactDOM from 'react-dom';
export default class Modal extends React.Component {
render() {
return ReactDOM.createPortal(
<div className='modalContainer'>
<div className='modalBox'>
{this.props.children}
</div>
</div>,
document.body
);
}
}
Haven't run into any issues with this pattern but I'd like to know if there are consequences as I start adding more libraries.
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. ReactDOM. createPortal(child, container) The first argument ( child ) is any renderable React child, such as an element, string, or fragment.
Because you won't be able to render an app to DOM without it. Your app probably has reactdom. render() in it and you don't realize it. Those are probably standalone examples—you need it once for every app.
ReactDOM is a package that provides DOM specific methods that can be used at the top level of a web app to enable an efficient way of managing DOM elements of the web page. ReactDOM provides the developers with an API containing the following methods and a few more.
ReactDOM provides the developers with an API containing the methods such as render(), findDOMNode(), unmountComponentAtNode(), hydrate(), and createPortal().
When a ReactDOM.createPortal is used in conjunction with a container in another window, the components do not respond to user input until after setState or forceUpdate are called on the parent component of the portal.
It renders the children into `domNode`. // `domNode` is any valid DOM node, regardless of its location in the DOM. return ReactDOM.createPortal( this.props.children, domNode ); } A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container.
Portal is not new concept in the react community. Many libraries are available that supports this kind of functionality. e.g react-portal and react-gateway. What happens when rendering any react app? Generally, when rendering any React application, a single DOM element is used to render the whole React tree.
Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the React tree regardless of position in the DOM tree. This includes event bubbling.
I am pretty sure that the same rules apply to portals as to usage of ReactDOM.render
. According to the portals documentation you provided, it is true that the portal is from the React's point of view a child of the React application (consider eg. the direction of the synthetic DOM event propagation), but physically the portal lives in separate context where React still needs to keep track of state changes and be in sync with the DOM.
If the parent of such context is the body
element, then the same amount of unwanted surprises is in stake like elements being inserted to it via 3rd party tools as stated in Dan Abramov's article. Simply put: As those DOM mutations from 3rd parties happen outside of React's control BUT modify the part of DOM that IS under React's control, it can lead to conflicts and inconsistencies.
Another point @RIYAJ KHAN has risen in his comment is what happens if suddenly the portal becomes parent of the application, especially if React sees them the other way around? The least I can think of are inconsistencies between native and synthetic DOM event propagation, where those two would propagate events in opposite directions between app and portal containers, which can get mind boggling if you often use both types of event handling (eg. synthetic in React component's event handlers and the native ones in RxJS operators).
Last but not least, what if you have more such portals which should be on the top DOM level, are you going to reuse the body
for all of them? That together with the 2 points above would create a turmoil.
The safest way is to create dedicated div
s under the body
just for the portals, this way they stay clean and free of unwanted magic.
Our experience so far on Material-UI has been that it's safe: https://github.com/mui-org/material-ui/issues/21626. We haven't seen any limitations reported by one of the 1m+ developers using the library yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With