Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use React 16 Portals

Tags:

html

reactjs

Lots of new functions released with React 16. One of them is the ReactDOM.createPortal(child, container) API, which is handy for visually breaking out of its container.

However, it seems like that it not only breaks out its container but also breaks the basic html rules which I learned from the first day of web development. The createPortal API let you render your component out of its parent, and break the html structure convention we expected.

In the other hand, we do retrieve more flexibility and now can render DOM in the sibling or else components.

IMO, I don't think this is a good deal to gain more flexibility by trading html convention in. Also the example supplied by official does not convince me.

What I am curious about is: Is there anyone who face any condition that createPortal API is a must?

thanks

like image 794
fung Avatar asked Nov 03 '17 13:11

fung


People also ask

Should I use React portals?

The Importance of Using Portals Below are the advantages of using React portals: React portals can use context to transfer data. Event Bubbling: By using the portal, which is situated outside the DOM tree, we can communicate with our parent component, which is located at the REACT DOM tree.

Why do we need React portals?

We mainly need portals when a React parent component has a hidden value of overflow property(overflow: hidden) or z-index style, and we need a child component to openly come out of the current tree hierarchy. Following are the examples when we need the react portals: Dialogs.

What does React createElement do?

createElement()Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span' ), a React component type (a class or a function), or a React fragment type.

When using a portal what is the second argument Reactdom createPortal XY?

To give you a brief explanation, the createPortal() function takes two arguments. The first one is the child that will be rendered. In our case, that's the Modal. The second argument is the container which represents the DOM element.


2 Answers

I ran into another use case a few months ago. Because React 16 portals were not available, I had to use a home-baked portal implementation.

I was creating SVG graphs. All of the lines, paths, and so forth needed to be rendered inside an <svg> element. But I wanted to use HTML to render text labels (for a number of reasons). This meant that an object on the graph and its label would necessarily be in separate parts of the DOM. But with portals, I could still keep all of a graph component's logic together. Here's a fictitious example:

const LabeledPoint = ({ x, y, r, labelText }) => [
    <circle cx={x} cy={y} r={r} />,
    <GraphLabel x={x + 5} y={y}>{labelText}</GraphLabel>,
];

You would use this component inside an <svg> element. The GraphLabel component would use a portal to render labelText in an HTML div element at the same coordinates as that <svg>, using absolute positioning to place it at the correct coordinates.

This way, all of the logic for a single component could be in one place even if I needed to render the actual DOM elements in different places for technical reasons.

like image 54
Thom Smith Avatar answered Sep 28 '22 15:09

Thom Smith


The examples in the docs are some of the cases where createPortal is really useful - specifically dialogs, hovercards, and tooltips.

The docs also specifically state:

Note:

It is important to remember, when working with portals, you’ll need to make sure to follow the proper accessibility guidelines.

As an example, the docs show how a modal could be built using createPortal(). You'll notice the modal is created in the #modal-root element, which is a root element alongside the #app-root element. This is a great example of how createPortal() can be used without violating any HTML rules.

<div id="app-root"></div>
<div id="modal-root"></div>
like image 35
Brett DeWoody Avatar answered Sep 28 '22 16:09

Brett DeWoody