React Portals in 3 Minutes
Tags: react, javascript, webdev, beginners
Published: 2019-12-17 19:36:01

> Grasp this awesome API for escaping DOM restraints whilst creating Portals 🕹😎


# What is it?
An API for rendering components outside of your app’s DOM hierarchy.

```javascript
ReactDOM.createPortal(<Component/>, DOMElement)
```
<figcaption>Intuitive API 👍</figcaption>

For those in camp __TL;DR__ scroll down for a demo!

# Why?
Perfect for scenarios where `CSS` styles are restraining your elements. For example, stacking(`z-index`) and `overflow` issues. You could even render things in a new `window`!  😎


[![Link to HackerNoon Article](https://thepracticaldev.s3.amazonaws.com/i/yeqfdeoi0b0ejf3hi0qv.png)](https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202)

# How?
Instead of returning an element in a component’s `render` method, return a portal.

```javascript
const Outsider = () => ReactDom.createPortal(<div>I am outside</div>, document.body)

const App = () => <Outsider/>
```
<figcaption>`Outsider` renders as a direct descendant of `document.body` 👍

# When to use?
- Modals
- Tooltips
- Floating menus
- Widgets

# Scope + Bubbling
A brilliant thing about portals is that a component rendered in a portal acts as if it is still in the React tree. It behaves like a normal React child. Pass it `props`, it will react to updates, etc.

Events fired in a portal will also bubble up through the `React` tree! Check out the example in the `React` docs.

[![Link to React Docs](https://thepracticaldev.s3.amazonaws.com/i/xm839mhoti5iz6y11v57.png)](https://reactjs.org/docs/portals.html#event-bubbling-through-portals)

# Basic example (Modal)
Let’s start with a common use case — the Modal. Modals are a great example of where we may need to render a component outside of the current DOM structure.

Our `Modal` will render based on a `state` value in the app.

```javascript
const Modal = ({ children, onClose, open }) =>
  open
    ? ReactDOM.createPortal(
      <div className='modal'>
        <button className='modal__close' onClick={onClose}>&times;</button>
        { children }
      </div>,
      document.body
    )
  : null
```

For our example, we will render the `Modal` on `document.body`. Our `Modal` is a functional component that accepts `children`, `onClose` and `open` as `props`.

Here it is in action!

{% codepen https://codepen.io/jh3y/pen/RwNozBm %}

# A silly example

Remember the video game "Portal"?

[![Link to Portal Video Game Wikipedia Article](https://thepracticaldev.s3.amazonaws.com/i/80ygt6gm31nmmye5n34n.png)](https://en.wikipedia.org/wiki/Portal_%28video_game%29)

Let’s create a scene 😅

Let’s start with a `Man` 🏃. We are going to use `Greensock`'s `Draggable` to create a draggable `Man`.

[![Link to GreenSock documentation for Draggable](https://thepracticaldev.s3.amazonaws.com/i/tnc41qlrrnjm3yboc5uj.png)](https://greensock.com/docs/Utilities/Draggable)

Now let’s create a scene with a "Portal". Our man will be bound by the app container.

```javascript
const App = () => (
  <Fragment>
    <Man bounds={rootNode} />
    <div className="portal portal--in"/>
  </Fragment>
)
```

That gives us

![Draggable Man concept where the Man Component is bound to a container](https://thepracticaldev.s3.amazonaws.com/i/g8ig71x8hs3x72fxjoz1.gif)

Now let’s get `ReactDOM.createPortal` involved 😃

We add an element into the `DOM` outside of our app (`#outside`). We also create `state` for tracking whether our `Man` is in or out of the app container.

We then use `createPortal` to render a `Portal` in `#outside`. And if `outside` is `true` we will use `createPortal` to render our `Man` in that outer element 👍

```javascript
<Man
  bounds={outside ? outsideElement : rootNode}
  onRelease={onRelease}
  outside={outside}
/>
<div className="portal portal--in" ref={innerPortalRef} />
{createPortal(
  <div ref={outerPortalRef} className="portal portal--out" />,
  outsideElement
)}
```


```javascript
const ManRender = () => (
  <div className="man" ref={manRef} role="img">
    🏃
  </div>
);

return outside ? createPortal(<ManRender />, bounds) : <ManRender />;
```

Our `Man` now invokes an `onRelease` function too. This checks our cursor position against our portal bounds on release. If we release over a portal, we toggle the `state` value. All the code is in the demo, there's not much to it 👍

![Clip of the working portal. Man component can be dragged in and out of the app container via the fictional portal](https://thepracticaldev.s3.amazonaws.com/i/t75ldniqfpapytz8hghq.gif)

If you use your dev tools to inspect the DOM, you’ll see the render happening outside `#app` 👍

{% codepen https://codepen.io/jh3y/pen/PXPJNV %}

# Notes 
- Don’t neglect [Accessibility](https://en.wikipedia.org/wiki/Web_accessibility)! Maintaining keyboard focus etc. is very important.
- Available in React@16.0.0+

# That’s it!
A 3-minute intro to portals in React!

![Link to React Docs on Portals](https://thepracticaldev.s3.amazonaws.com/i/ot1x8wedvj94hif8npir.png)

As always, any questions or suggestions, please feel free to leave a response or [tweet me 🐦](https://twitter.com/@jh3yy)! I'd love it if you connected with me on the socials 😎