paint-brush
Portals are lit 🔥 by@aswath
388 reads
388 reads

Portals are lit 🔥

by AswathJuly 29th, 2019
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Recently I was introduced to Reacts' createPortal API, which was nothing short of amazing. Portals provide a way to render children of a react component somewhere else in the DOM, not in the same hierarchy. It can be widely used when a parent component has an overflow: hidden or z-index style, but you need the child to visually "break out" of its container. For example, dialogs, hovercards, and tooltips. The hierarchy is unaltered in the Virtual DOM, so event bubbling will happen with ease.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Portals are lit 🔥
Aswath HackerNoon profile picture
Recently I was introduced to Reacts' createPortal API, which was nothing short of amazing.

Let me share my experiences with it!

Being a professional Ember developer, my love towards React has never faded away. React with its' component oriented architecture boosts productivity, ensures stable code and is backed up with strong community.

I don't wanna bore you, with this sort of things that you(probably many Web devs) hear in routine.

I think, Its' time to get our hands dirty with Portals 🔥

'Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component'

Generally, not everyone in the world can understand the definition in the official docs in a single glance!, atleast NOT ME! (jus kidding, Reacts' docs on Portals is more beginner friendly peeps, go check it out)

So i decided to have a practical approach with it:

As stated in the definition, Portals provide a way to render children of a react component somewhere else in the DOM, not in the same hierarchy!

As soon i realised it, i was ended up with nothing but questions.

OMG what about the event bubbling? and many…

Being a professional ember developer, i have used Ember Wormhole, it is an addon probably does the similar work of Portals in Ember.

I kept digging more about Portals. One thing i explored is its' use-case in Modal Dialogs.

I built a modal component with bootstrap(overriding some of bootstrap styles) in react similar to this 👇

//Modal.js
import React from "react";
import ReactDOM from "react-dom";
export default class Modal extends React.Component {
  onClose = e => {
    this.props.onClose && this.props.onClose(e);
  };
  render() {
    let modal = (
      <div
       class="modal fade"
       id="exampleModalCenter"
      >
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLongTitle">
              Modal title
            </h5>
            <button
              type="button"
              class="close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">...</div>
          <div class="modal-footer">
            <button
              type="button"
              class="btn btn-secondary"
            >
              Close
            </button>
            <button type="button" class="btn btn-primary">
              Save changes
            </button>
          </div>
        </div>
      </div>
    </div>
    );
    return (modal);
  }
}


I rendered it as a child to App 👇

//App.js    
import React from "react";
import Modal from "./Modal-Compo";
export default class App extends React.Component {
  onClose = e => {
    this.props.onClose && this.props.onClose(e);
  };
 render() {
    let alignCenter = {
      display: "flex",
      alignItems: "center",
      justifyCenter: "center",
      height: "200px",
      overflow: "hidden",
      width: "50%",
      margin: "auto",
      marginTop: "10%"
    };
    return (
    <div style={alignCenter}>
      <p style={{ height: "100%", margin: "0" }}>
        //some random 100 lines
      </p>
      <Modal onClose={this.onClose}/>
    </div>
  )
 }
}


Atlast rendered the App component in the root element 👇

//Index.js
import React from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "jquery/dist/jquery.min.js";
import "bootstrap/dist/js/bootstrap.min.js";
import App from "./components/App";
import "./styles.css";
function WhatAreModals() {
  return (
    <div style={{ height: "100vh" }} className="App">
      <App />
      <button
        type="button"
        className="btn btn-primary"
        data-toggle="modal"
        data-target="#exampleModalCenter"
      >
        Launch demo modal
      </button>
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<WhatAreModals />, rootElement);

Finally my prototype was ready 😃

When i clicked the Launch demo modal CTA, this happened (oopsy) 😕


The culprit is the App component styled 'overflow:hidden', as in our case the Modal component is rendered as a child of App whose overflow is hidden, our Modal never shows up 😩

Here is where the life saver Portal comes in 🔥

I just made a tweak in my Modal component and the index.html(created another root element for Modal to be rendered)

//index.html
<div id="root"></div>
<div id="modal-root"></div> //added this

Rendered Modal in Portal, changed return statement by implementing createPortal

//Modal.js
ReactDOM.createPortal(modal, document.getElementById("modal-root"));

It worked seamlessly,


The problem was solved by breaking the Modal component out of the container, out of the hierarchy.

But suddenly i got into a confusion, as the hierarchy is broken i doubted whether event bubbling will occur? (I think, Many will question this!).

I went on digging deeper 😁

Native DOM Snapshot:


React DOM:

Finally, i was satisfied seeing this, probably many would be 😌

From the snapshots, we come to know that the hierarchy is unaltered in Reacts' Virtual DOM, so event bubbling will happen with ease.

Portals can be widely used when a parent component has an overflow: hidden or z-index style, but you need the child to visually "break out" of its container. For example, dialogs, hovercards, and tooltips.

I feel this post would've satisfied you on Reacts' createPortal API, if yes, feel free to share this with your colleague web devs as well.