Difference between attaching React portal directly to DOM node vs to a detached node?

Viewed 847

Regarding React portals, what is the difference between creating a detached node then appending it to the document vs directly having the portal rendered into the document?

In the docs (https://reactjs.org/docs/portals.html) the following is there as an example. On mount, a dynamically created DOM node (this.el) is appended to the portal div. But what's the difference between just appending it directly to the modalRoot element in the document? I don't quite get the commented section of the code.

const modalRoot = document.getElementById('modal-root');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // The portal element is inserted in the DOM tree after
    // the Modal's children are mounted, meaning that children
    // will be mounted on a detached DOM node. If a child
    // component requires to be attached to the DOM tree
    // immediately when mounted, for example to measure a
    // DOM node, or uses 'autoFocus' in a descendant, add
    // state to Modal and only render the children when Modal
    // is inserted in the DOM tree.
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el
    );
  }
}
2 Answers

I think it's all about descendant components.

In the example above, componentDidMount will be called, after all descendants has mounted, and only after that, all descendants will be attached to the dom.

But you can have some logic in descendants, which requires them to be in dom.

For example, you can have child component which uses ref to calculate self position in the document, this can be done only if ref is attached to real dom.

Second example, your child input can do autofocus in componentDidMount. This also will take effect, only of component is already in real dom.

In these cases, you need to prevent children from rendering, until this.el will be attached to the dom

With appendChild, the child element belongs to the same DOM and virtual DOM tree as the container. It will be affected by all cascading behaviors such as events or styles.

The Portal allows you to manage the child in a separate branch of the virtual DOM, where you have more granular control.

Simple example: if your child is a tooltip, the Portal allows you to consistently style it regardless of the container styles.

Related