Learn React Portal and Its Applications
Tags: javascript, tutorial, webdev, react
Published: 2021-11-23 09:04:02

---
title: Learn React Portal and Its Applications
published: true
date: 2021-09-25 11:21:52 UTC
tags: javascript, tutorial, webdev, react
canonical_url: https://www.upbeatcode.com/react/learn-react-portal-and-its-applications/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rld0bz3wnynzmaxgrhk3.png
---

React Portal is a great way to render floating components. React Portal renders child components into a DOM node without disturbing event propagation and provides greater flexibility outside of the hierarchy of a parent container.

React Portals have made it easier to create floating modals. It provides an escape from monotonous hierarchy with the help of Portals. But at the same time, React Portals do not disturb event propagation. The parent component is listening to those events; thus, making it more feasible to handle the events across an application.

Let’s look at the creation of React Portal in this article.

# React Portal — Example

The syntax of React Portal is:

```js
ReactDOM.createPortal(child, container)
```

In this syntax, the first argument is the React child component. It could be a string or a fragment, or an element. The second argument is the DOM element.

To create a new DOM node, navigate to the `public/index.html`file and type:

```html
<div id="root"></div> <!-- this is root node -->
<div id="portal-root"></div> <!-- this node portal node -->
```

Now, to implement React Portal, create a _js_ file. Let’s name it _`Modal.js`_. In this file, write the code to create a modal.

```jsx
import ReactDOM from "react-dom";

export default function Modal() {
  const portalDOM = document.getElementById("portal-root");
  return ReactDOM.createPortal(<div>Modal Portal</div>, portalDOM);
}
```

Now, add the modal in the `App.js` file of the React application.

```jsx
import React from "react";
import "./App.css";
import Modal from "./components/modal";

class App extends React.Component {
  render() {
    return (
      <div>
        <Modal />
      </div>
    );
  }
}

```

In this example, the `App.js`file renders the modal that you created. If you inspect the code using the browser dev tool, you will see that it is evident that the modal has its `div`element.

# Common Use Cases of React Portals

The most common use cases for React Portals are tooltips, dialog boxes, hover cards, modals, or loaders. You can also use React Portals when the child component should be visually separate from the parent container. It is even more useful when a parent component has `overflow: hidden` or `z-index` styling settings.

Whatever the use case may be, there are some points that you must keep in mind while working with React Portals:

- Events will be propagating to the React tree ancestors.
- React has control over the child component’s lifecycle even when using the Portals.
- Portals affect the HTML DOM structure and not the React tree.
- You need to define an HTML DOM element as a mount point for the Portal’s component.

# How to Use React Portal in React — A Modal Example

One of the most common use cases is Modals in React. Lots of applications use Modals because it improves the overall UX of the application. Furthermore, they are useful in grabbing the user’s attention. [React official documentation](https://reactjs.org/docs/portals.html) also uses Modals as an example to demonstrate how the models work perfectly.

Before you start with the modal implementation, make sure that React is updated to the latest version.

Like the sample example shown above, add the _modal_ `div`above root`div`_._

```html
<div id=”modal”></div>
<div id=”root”></div>
```

Now, create a Modal component and name it `Modal.js`_._ This component will act like a modal, and you can put content inside it.

```jsx
import React from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal");

class Modal extends React.Component {
  constructor(props) {
    super(props);
    // Create div for this modal
    this.element = document.createElement("div");
  }
  // Append div to the div#modal
  componentDidMount() {
    modalRoot.appendChild(this.element);
  }
  /**
   * Make sure to remove the div when it is closed, and save the memory.
   */

  componentWillUnmount() {
    modalRoot.removeChild(this.element);
  }
  render() {
    return createPortal(this.props.children, this.element);
  }
}
export default Modal;

```

Add CSS to your file as per your requirements to set the layout. In the next step, add import this Modal into any of your components.

```jsx
import React from "react";
import Modal from "./Modal";

export default class Home extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false,
    };
  }
  toggleModal = () => {
    this.setState({
      showModal: !this.state.showModal,
    });
  };
  render() {
    const { showModal } = this.state;
    return (
      <React.Fragment>
        <button className="modal-toggle-button" onClick={this.toggleModal}>
          {!showModal ? "Open Modal" : "Close Modal"}
        </button>
        {showModal ? (
          <Modal>
            <h1>Sample Heading</h1>
            <p>Sample Paragraph</p>
            <button className="modal-close" onClick={this.toggleModal}>
              X
            </button>
          </Modal>
        ) : null}
      </React.Fragment>
    );
  }
}
```

In this code, we’ve set the `showModal`property to false. The Modal will be visible at the click of the button.

# Event Bubbling in React Portals

Although you can create a React Portal anywhere in the document, it is still under the _React tree_, regardless of its position in the _DOM hierarchy_. The same happens when the child component propagates the event. The event fired from the child propagates to its ancestors in the _React tree_, even if they do not exist in the _DOM hierarchy_.

Let’s look at an example of event bubbling.

For instance, you have this HTML structure:

```html
<html>
<body>
<div id=”app-root”></div>
<div id=”modal-root”></div>
</body>
</html>
```

A parent component in `#app-root` will be able to catch a bubbling event from its sibling node `#modal-root` as both are sibling containers in the DOM.

```jsx
const appRoot = document.getElementById("app-root");
const modalRoot = document.getElementById("modal-root");

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement("div");
  }
}
```

The Modal’s children are mounted on a detached DOM node. If there is a need to attach a child component to the DOM tree, add the state to the Modal and only render the child component.

```jsx
import React from "react";

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { clicks: 0 };
    this.handleClick = this.handleClick.bind(this);
  }

  componentDidMount() {
    modalRoot.appendChild(this.el);
  }
  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }
  render() {
    return ReactDOM.createPortal(this.props.children, this.el);
  }
}
```

The event `handleClick()` will fire when you click the button in Child. Keep in mind that the button is not the immediate descendant in the DOM hierarchy.

```jsx
handleClick() {
    this.setState(state => ({
      clicks: state.clicks + 1
    }));
}

render() {
    return (
      <div onClick={this.handleClick}>
        <p>Number of clicks: {this.state.clicks}</p>
        <Modal>
           <Child />
        </Modal>
      </div>
    );
}
```

A click on the button will trigger an event that will bubble up to the parent as we have not defined any `onClick`attribute.

```jsx
function Child () {
    return (
      <div className="modal">
       <button>Click</button>
      </div>
    );
}

ReactDOM.render(<Parent />, appRoot);
```

# Conclusion

In this article, you learned about React Portal in React Application, its use case, and event bubbling. The concept is easy; however, it provides the flexibility to handle reusable components outside the DOM hierarchy without breaking the default event behavior.