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 profressional 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">×</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>
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.
Top comments (2)
Very cool!
I believe it's the same concept as Angular Portal
Absolutely π π