Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make ReactDOM.createPortal insert element as first child of target container (instead of last child)

So I'm using ReactDOM.createPortal to render an element outside it's normal DOM placement. I have to do it since I'm interacting with a library that creates it's own elements (outside my scope) and I have to place one of my DOM elements inside theirs.

What I'm getting using createPortal is:

<div class="target">
    <div />
    <div class="myDiv" />
</div>

What I'm trying to achieve:

<div class="target">
    <div class="myDiv" />
    <div/>
</div>

I cannot seem to find how to change the behaviour of createPortal make it insert the node as first child.

like image 727
jeffarese Avatar asked Oct 05 '18 05:10

jeffarese


People also ask

What is second argument in createPortal?

createPortal(child, container) The first argument ( child ) is any renderable React child, such as an element, string, or fragment. The second argument ( container ) is a DOM element.

Is ReactDOM render necessary?

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.

What is ReactDOM unmountComponentAtNode?

React has a top-level API called unmountComponentAtNode() that removes a component from a specific container. The function unmountComponentAtNode() takes an argument as a container from which the specific component should be removed. Below is the basic syntax of the function unmountComponentAtNode() . 1ReactDOM.

How do you make a component portal?

A Portal can be created using ReactDOM. createPortal(child, container) . Here the child is a React element, fragment, or a string, and the container is the DOM location(node) to which the portal should be injected. Following is a sample modal component created using the above API.

How to render the Portal component’s children using reactdom?

To render the Portal component’s children, we make use of ReactDOM.createPortal (). This is a special ReactDOM method that accepts the children and the element we created. To see how the Portal works, let’s make use of it in our App component. But, before we do that, let’s cover the basics of how we want the App to function.

What is the difference between target container and child in ReactJS?

The first argument (child) is any renderable React child, such as an element, string, or fragment. The second argument (container) is a DOM element. You passed in a string instead of a DOM element. I am having the same problem but a different cause. @danielduan ? Thank you in advance! Target container is not a DOM element.

What is portal in React Native?

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.

How does the parent react to the button click event?

So the outputted element’s parent actually listens for the button click event and allows the child to be inserted even though it and the button are separate siblings in the DOM. Let’s break down the steps for creating this toggled Portal element to see how it all works.


1 Answers

React will use appendChild to render a portal, this behaviour is intrinsic and not subject to change.

If a portal should be shown before other children, a container should be provided in existing DOM:

<div class="target">
    <div class="portal-container">...rendered portal...</div>
    <div />
</div>

If this isn't possible, DOM should be accessed directly to prepend a container programmatically, similarly to this guide example:

class PrependedPortal extends React.Component {
  portalRoot = document.querySelector('.target');
  portalContainer = document.createElement('div');

  componentDidMount() {
    this.portalRoot.prepend(this.portalContainer);
  }

  componentWillUnmount() {
    this.portalRoot.removeChild(this.portalContainer);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.portalContainer
    );
  }
}

prepend isn't well-supported and needs to be polyfilled or replaced with similar DOM manipulations, e.g. jQuery prepend.

like image 105
Estus Flask Avatar answered Sep 20 '22 16:09

Estus Flask