Is it safe to use ReactDOM.createPortal() with document.body?
Asked Answered
M

2

18

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.

Mccutcheon answered 27/3, 2018 at 4:47 Comment(1)
App root always child of . Body and by rendering portal on body means putting whole app as a child of portal which is worstBipack
B
8

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 divs under the body just for the portals, this way they stay clean and free of unwanted magic.

Bartley answered 27/3, 2018 at 6:43 Comment(1)
Thank you for pointing this out @Dan, I often see people using createPortal(portal, document.body) and wasn't aware of the caveats. Could you please take a look at my question at your convenience? I'm encountering some unexpected event behaviour when I mount a portal to document.body but can't make out what's causing it.Brainpan
T
3

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.

Tortoni answered 30/6, 2020 at 11:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.