Consider a component which needs to manage subcomponents that are not children in its own DOM tree, but must be added to the top-level document.

A typical example would be an autocompletion field that needs to show autocompletion matches in a floating menu below the input field. The floating menu necessarily needs to be added as a child of the document body element to escape any "overflow: hidden" constaints in the tree that would prevent it from showing. The floating menu needs to be removed after it's no longer used.

In such a case, the logical approach seems to be to mount a component in an arbitrary div, and later unmount it when it's no longer needed. However, this introduces an interesting state-flow problem when events are used to trigger such an unmount.

Here is an excerpt from my current code, to illustrate the problem:

componentDidUpdate: function(prevProps, prevState) {
  if (prevState.matches !== this.state.matches) {
    if (this._floater) {
      this._floater = null;

    if (this.state.matches.length > 0) {
      this._floater = Floater.create(

handleSelectionChange: function(items) {
  this.setState({matches: [], selectedItem: items[0]});

Here, Floater is a generic component that can contain any other component; it sets itself to absolute, positions itself and so on. Floater.create() is a convenience method to create a floater component and insert it into the document.

Floater.remove() currently looks like this:

remove: function() {
  var self = this;
  if (this.isMounted()) {
    window.setTimeout(function() {
    }, 10);

The reason it's using a timeout is to allow the parent component to be able to remote it after a state update. Selecting something in the SelectableList would trigger a handleSelectionChange in the parent, which would call remove() to unmount the component while it's still being used. It's ugly, although it does work.

Is there a better, more idiomatic way?



Just a head-up for visitors to this question.

As of React v16, there is a specific feature to handle this very case. It is called Portal

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow