Skip to content

Instantly share code, notes, and snippets.

@jonidelv
Last active June 21, 2020 23:19
Show Gist options
  • Save jonidelv/ec20fce593c2039da7392970d8a47162 to your computer and use it in GitHub Desktop.
Save jonidelv/ec20fce593c2039da7392970d8a47162 to your computer and use it in GitHub Desktop.
React Portals

React Portals

What are Portals? how and when to use it

React v16 introduced a new feature called portals. Portals provide a quick and easy way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. React render the entire app under a single DOM node — the app root. But what if you want to render children outside the root DOM node? that's when you use Portals.

When

Two examples for doing this are when the parent element has styling (like a z-index pushing it to the front of the page or an overflow: hidden) but you want the child to visually appear on top of its container.

How does it work

A portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the React tree regardless of position in the DOM tree. This includes event bubbling. An event fired from inside a portal will propagate to ancestors in the containing React tree, even if those elements are not ancestors in the DOM tree.

Usage

I recommend it creating a component, and then using every time we need to. First, we need to create a DOM element (like the root element we created to append the app) in your index.html, this is where all the portals components are going to be attached.

  <div id="portal-components"></div>
  <div id="root">

Then create the Portal component

import { PureComponent } from 'react'
import ReactDOM from 'react-dom'

const rootElement = document.getElementById('portal-components')

class Portal extends PureComponent {
  constructor(props) {
    super(props)
    this.el = document.createElement('div')
  }

  componentDidMount() {
    rootElement.appendChild(this.el)
  }

  componentWillUnmount() {
    rootElement.removeChild(this.el)
  }

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

export default Portal

Then use it like so

<Portal>
  {Everithing here is going to be attachaded outside the root DOM node}
</Portal>

Note

When using Portals, everything inside the <Portal> component is going to be placed absolute to the screen, I recommend using CSS fixed positions to adjust alignments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment