DEV Community

Cover image for React Portals in 3 Minutes
Jhey Tompkins
Jhey Tompkins

Posted on

React Portals in 3 Minutes

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.

ReactDOM.createPortal(<Component/>, DOMElement)
Enter fullscreen mode Exit fullscreen mode
Intuitive API 👍

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

How?

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

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

const App = () => <Outsider/>
Enter fullscreen mode Exit fullscreen mode

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

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.

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

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!

A silly example

Remember the video game "Portal"?

Link to Portal Video Game Wikipedia Article

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

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

const App = () => (
  <Fragment>
    <Man bounds={rootNode} />
    <div className="portal portal--in"/>
  </Fragment>
)
Enter fullscreen mode Exit fullscreen mode

That gives us

Draggable Man concept where the Man Component is bound to a container

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 👍

<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
)}
Enter fullscreen mode Exit fullscreen mode
const ManRender = () => (
  <div className="man" ref={manRef} role="img">
    🏃
  </div>
);

return outside ? createPortal(<ManRender />, bounds) : <ManRender />;
Enter fullscreen mode Exit fullscreen mode

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

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

Notes

That’s it!

A 3-minute intro to portals in React!

Link to React Docs on Portals

As always, any questions or suggestions, please feel free to leave a response or tweet me 🐦! I'd love it if you connected with me on the socials 😎

Top comments (6)

Collapse
 
fly profile image
joon • Edited

I read articles about using react portals, but never really felt the need to use it itself.... until now. Modals appear to be the perfect use-case, I've been giving far too high zIndexs to my modals :)

Thank you immensely for the post Jhey. It has truly widened my perspective on coding with React.

Collapse
 
jh3y profile image
Jhey Tompkins

Hey joon 👋
No problem! I'm glad I could help 😊We can do some pretty cool things with Portals 😎

Collapse
 
bloycey profile image
Andrew Bloyce

I am so glad you used an example from the portal game here. Perfect.

Collapse
 
jh3y profile image
Jhey Tompkins

I felt obliged 😅I'm glad it's appreciated!

Collapse
 
burzumumbra profile image
Ronald Flores Sequeira

Really awesome introduction to Portals, I feel the need to try it.

Collapse
 
jh3y profile image
Jhey Tompkins

Thanks Ronald! 😊I appreciate that. Try it out, it's quite cool what opportunities it provides.