The  React v16.0 release was a big one and among the changes are fragments, error boundaries, portals, support for custom DOM attributes, improved server-side-rendering and reduced file size. We will talk about the Portals here.

What is React Portal?

A way of rendering a child component outside the present Dom-Node-Hierarchy as opposed to the traditional method of child component rendered inside the parent component.

How to create a portal?

ReactDOM.createPortal(child, container)

* child – the component that is to be rendered, this could be a string, a fragment or an element.

* container -the DOM element to render into

What is the need of this change?

The traditional way of rendering has no faults, however sometimes the use case might want us to to insert a child into a different location in the DOM.

Usage:

  • Example 1:
Traditional use (Scenario 1)Using Portals (Scenario 2)
render() {

children into it

 return (

   <div>

     {this.props.children}

   </div>

 );

}

 

render() {

 return ReactDOM.createPortal(

   this.props.children,

   myNode,

 );

}

 

 

Scenario 1 vs Scenario 2:

In Scenario 1,  React mounts a new div and renders the children into it while in Scenario 2  React does not  create a new div. It renders the children into `myNode`(which is any valid node and can be placed anywhere in the app)

Example 2:

 index.html

<div id="root"></div>

<div id="root-dup"></div>

<div id="root-dup-again"></div>

 

App.jsx

 

import React from 'react';

import { render, createPortal } from 'react-dom';

import HelloChild from './HelloChild.react'

const main = document.getElementById('root');

const portal_1 = document.getElementById('root-dup');

class App extends React.Component {
 render() {

  return (

   <div>

    <h1>I am the main component!!</h1>

    <Hello value=" Hey, I am a child of ‘App’ class."/>

   {createPortal(<HelloChild value="Hey, I am the child node of ‘Hello’ class but here, I am used as a portal attached to ‘App’ class." />, portal_1)}

  </div>

 );

}}
render(<App />, main);

 

HelloChild.jsx

 

import React from 'react';

import { render} from 'react-dom';

export default class HelloChild extends React.Component {

  render() {

   return (

    <div>

      <h1>{this.props.value}</h1>

    </div>

  );

 }

}


Hello.jsx

 

import React from 'react';

import { render} from 'react-dom';

import HelloChild from './HelloChild.react'

export default class Hello extends React.Component {

 render() {

  return (

   <div>

    <h1>{this.props.value}</h1>

    <HelloChild name=" Hey, I am the child 'Hello' class"/>

   </div>

  );

 }

}

Output:

Screen Shot 2018-01-19 at 12.40.38 PM

Event Bubbling in Portals:

The React docs reads out:

 

Even though 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 its 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.”

 

Example:

index.html

 

<div id="root"></div>

<div id="root-dup"></div>

App.jsx

 

const main = document.getElementById('root');

const portal_1 = document.getElementById('root-dup');



class HelloPortal extends React.Component {//the portal component

 constructor(props) {

   super(props);

   this.el = document.createElement('div');

 }

 componentDidMount=()=>{

   portal_1.appendChild(this.el);

 }

 render() {

   //the portal is created here

   return ReactDOM.createPortal(

     this.props.children,

     this.el,

   );

 }

}

class App extends React.Component {

 constructor(props) {

   super(props);

   this.state = {

     sum: 0

   };

 }

 handleClick=()=>{

   this.setState({

     sum: this.state.sum + 50

   });

 }

 render() {

   return (

     <div>

       <p>(click anywhere inside this Grey Box or on the Blue Button to add Rs. 50 to your Wallet)</p>

     <div className ="grey-div" onClick={this.handleClick}>{/*this handle click is on the div*/}

       <p>Wallet Amount:  {this.state.sum}</p>        

       <HelloPortal>{/*this fires the handle click of the above div in absence of a handle click of this own*/}

         <Linker />{/*the ‘Add’ button*/}

       </HelloPortal>

     </div>

     </div>

   );

 }

}
Linker = () => {

return (

   <div>

     <button class="btn">Add 50</button>

   </div>

 );

}
ReactDOM.render(<App />, main);

 Output: Screen Shot 2018-01-19 at 11.12.38 AM

In the above example, the event ‘handle click’ is attached to the grey div and should be fired inside it. Since, Add button is a child of that div, even if its portal, it will still follow through the handleClick, in absence of its own handleClick event.

 

Looking for ReactJS Development Company, hire our dedicated developers!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.