Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to render a react portal into another component DOM?

Consider the following example:

class GridContainer extends React.Component {
  ...
  render (){
    return <div>
      <Pagination portalId="portal-id"></>
      <Grid ...>
    </div>
  }
}

class Grid extends React.Component {
  ...
  render (){
    return <div>
      <div id="portal-id"></>
      <table ...>
    </div>
  }
}

class Pagination extends React.Component {
  ...
  render (){
    return return ReactDOM.createPortal(<div>Paginator DOM...</div>, document.getElementById(this.props.portalId));
  }
}

Is it safe to render a portal inside other components DOM? I've tested it and it works, but I don't know if this is reliable. The Portals doc mention that you can render a portal in a DOM node but nothing about components DOM.

Why is this different (speculating here)? while updating the portal parent component, in the reconciliation process the diff might find the inconsistency and remove the portal node.

From my testing, the above doesn't happen but I don't know if I can assume that react handles it. So here comes the Q:

Is it safe to render a portal into another component DOM?

like image 938
Luis Sepulveda Hidalgo Avatar asked Dec 27 '18 19:12

Luis Sepulveda Hidalgo


People also ask

Can I have multiple React DOM render?

Before React 16.2, you could render only a single DOM node inside the render method. Now you can render multiple DOM nodes. In order to do this, wrap it inside a parent div which essentially makes it a single DOM node with multiple elements inside it. Fragments in React do not deviate much from their literal meaning.

Which of the following would be the best use case for using React portals?

React Portal comes in handy when we need to render child components outside the normal DOM hierarchy without breaking the event propagation's default behavior through the React component tree hierarchy. This is useful when rendering components such as modals, tooltips, popup messages, and so much more.

When using the portal what is the second argument?

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. The first argument ( child ) is any renderable React child, such as an element, string, or fragment. The second argument ( container ) is a DOM element.

Are React portals good?

This is where React Portals are advantageous. React Portals provides the ability for an element to render outside the default hierarchy without compromising the parent-child relationship between components.


1 Answers

Is it safe? Sure, but it probably won't work the way you expect.

First off, you can totally dump dom inside a div that React created.

I've met several React programmers who would contest this fact, but Reacts design expects and accounts for editing dom directly when necessary. If they didn't, there would be no componentDidUpdate or React refs.

This documentation on integration with other libraries is probably the most relevant.

Here's the scoop:

  • React won't touch the internals of a rendered div, assuming it's always empty at the end of render. It will only:
    • Create new elements, which is irrelevant here as long as you leave it empty.
    • Update existing elements that were originally created by react.
    • Delete elements that were originally created by react.

So just create that empty div and leave it alone in render and React won't mess with it.

Here's the rub; React guarantees nothing about the timing of the renders.

This means that you have no idea if the element will actually be there when Pagination renders, causing the query to fail and the portal to not display. componentDidUpdate only works because React specifically runs it after the dom is updated. But render is run before the dom is updated. So if Pagination is rendered in the same sweep as Grid that div is likely not mounted yet.

Now the infamous stack overflow Just-Don't-Do-That answer:

Just don't do that. The purpose of portal is to let you render outside the React container while keeping your components inside of Reacts render tree. If you're rendering inside React render tree anyways why don't you just render the components there? (if that statement is confusing I blame you)

like image 137
R Esmond Avatar answered Sep 30 '22 17:09

R Esmond