A Beginner's Guide to Portals in React: Everything You Need to Know
Tags: react, webdev, javascript, beginners
Published: 2023-04-07 20:39:19

React is a popular JavaScript library for building user interfaces. One of the powerful features of React is the use of portals, which allow developers to render content outside of the normal React tree structure. In this article, you'll learn all about what portals are, how to use them, and some common use cases for portals in React applications.

## What are Portals?

React portals provide a way to render content outside of the normal DOM hierarchy of a component. This means that you can render a child component at a different place in the DOM tree than its parent component.

In technical terms, portals in React work by creating a new DOM node and rendering a component into it. This new node is appended to the body element of the HTML document, which is outside of the normal React component tree. The rendered content can then be positioned and styled independently of the parent component.

## Advantages of Using Portals

There are several advantages to using portals in React:

* **Flexibility**: Portals allow you to render a component outside of its parent container, which can be useful in situations where you need to display content in a different part of the page.
    
* **Improved performance**: By rendering a component outside of its parent container, you can reduce the amount of DOM manipulation needed to update the component, which can improve performance.
    

## Common Use Cases for Portals

Portals can be used for a variety of UI elements. Here are some common use cases of portals in React:

* Modals
    
* Dialog boxes
    
* Tooltips
    
* Hover cards
    
* Popovers
    
* Dropdown Menus
    
* Loaders
    

## How to Create a Portal in React

To create a portal in React, we make use of the [`createPortal()`](https://react.dev/reference/react-dom/createPortal) API. This method takes two arguments:

1. `children`: Any valid React element that can be rendered.
    
2. `domNode`: DOM container where the `children` should be rendered
    

Here is the syntax:

```javascript
createPortal(children, domNode);
```

Example:

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

const Modal = () => {
  return (
    <div className="modal">
      <h1>Modal Content</h1>
    </div>
  );
};

const Portal = () => {
  return createPortal(<Modal />, document.getElementById("modal-root"));
};
```

In the example above, we define a Modal component that we want to render using a portal. We then define a Portal component that uses the `createPortal()` method to render the Modal component in a container with the ID of `modal-root`.

## How to Use Portals

To see how portals work, let's create a simple React app that uses portals to render a modal component. If you're working on an existing project, you can skip the first step. The complete code for this example is available on [GitHub](https://github.com/israelmitolu/React-Portals-Demo).

### Step 1: Initialise your React app

First, create a [new React app](https://israelmitolu.hashnode.dev/why-you-should-ditch-create-react-app-for-vite) using Vite:

```bash
npm create vite@latest my-react-app --template react
```

Navigate to the project directory and install the dependencies:

```bash
cd my-react-app
npm install
npm run dev
```

### Step 2: Create a portal container

Next, create a container element in the `index.html` file that will host the portal. This element should be located outside the root node of the React app, which is typically a div with an ID of `root`.

For this example, we'll create a div with an ID of `portal` and add it to the body of the HTML file:

```html
<body>
  <div id="root"></div>
  <div id="portal"></div>
</body>
```

### Step 3: Create the Overlay component

We will use the Overlay component as a backdrop effect when the modal opens, and also create the portal inside it.

Create a new file `Overlay.jsx`, in the `src` directory and paste the following code:

```jsx
import React from "react";
import { createPortal } from "react-dom";
import "./App.css";

const Overlay = ({ closeModal, children }) => {
  return createPortal(
    <div className="overlay" onClick={closeModal}>
      {children}
    </div>,
    document.getElementById("portal")
  );
};

export default Overlay;
```

The Overlay component returns a JSX fragment that uses the `createPortal()` method from the `react-dom` package to render a div with children elements inside a portal.

We then set the `onClick` event for the div to call the `closeModal` function that is passed as a prop.

### Step 4: Create the Modal component

Next, create a new file `Modal.jsx` in the `src` directory, and add the following code.

```jsx
import React from "react";
import Overlay from "./Overlay";
import "./App.css";

const Modal = ({ closeModal }) => {
  return (
    <Overlay closeModal={closeModal}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Modal</h3>
        <p>
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Odit, libero.
          Exercitationem quod quam perspiciatis quasi voluptate sint facilis
          quia praesentium pariatur veniam quidem nam, ullam porro eveniet
          molestiae minima eligendi.
        </p>
        <button onClick={closeModal}>Close</button>
      </div>
    </Overlay>
  );
};

export default Modal;
```

In the code above, the `onClick` event for the div is set to stop event propagation so that clicking inside the modal doesn't close it.

Additionally, the `onClick` event for the button element will call the `closeModal` function that was passed as a prop.

### Step 5: Edit the App component

Copy and paste the following code into the `App.jsx` file.

```jsx
import { useState } from "react";
import Modal from "./Modal";
import "./App.css";

function App() {
  // State to manage whether the modal is open or closed
  const [modalOpen, setModalOpen] = useState(false);

  // Function to toggle the state between open and closed
  const handleModal = () => {
    setModalOpen(!modalOpen);
  };

  return (
    <div className="App">
      <h1>React Modal Demo</h1>
      <p>
        This is a demo of how to use portals to create a modal component in
        React.
      </p>
      <button onClick={handleModal}>Open Modal</button>

      {modalOpen && <Modal closeModal={() => setModalOpen(false)} />}
    </div>
  );
}

export default App;
```

Here we define a state to manage whether the modal is open or closed, and a function to toggle the state. When the "Open Modal" button is clicked, the `handleModal` function is called and the `modalOpen` state is updated accordingly.

If the state is `true`, the Modal component is rendered, which includes a "Close" button that sets the modalOpen state to false.

### Step 6: Style the App

Finally, let's style the app. Add the following code inside the `App.css` file:

```css
.App {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: #f5f5f5;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal {
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: absolute;
  width: 450px;
  min-height: 250px;
  padding: 2rem;
  top: 20%;
  background-color: white;
  border-radius: 15px;
}

button {
  padding: 0.7rem 1.4rem;
  color: white;
  border-radius: 5px;
  text-align: center;
  cursor: pointer;
  font-weight: 600;
}
```

Here's what the final app looks like:


![React Modal demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z37bba9it5wrkx8r88sk.gif)

Now, let's take a closer look at how this works. Open the **Developer Tools** in your browser and inspect the page. You'll notice that while the modal is closed, the `portal` div is empty.


![DevTools with modal closed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2j4nl4nm8eiilbhiuq0.PNG)

When you click the button to open the modal, the modal is rendered inside the `portal` div, just as we specified.


![DevTools with modal open](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nb10e6281crupo9hun00.PNG)

The new DOM nodes are now mounted inside the `portal` node instead of the `App` node specified in the source code. This demonstrates the functionality of portals in action.

## Event Bubbling and Portals

Event bubbling refers to the way events propagate from child components to parent components in the component tree. In the case of React portals, this means that even if we render a portal outside of the parent DOM element, it still behaves like a standard React component, with access to props and state, as it remains within the DOM tree hierarchy.

Since portals only affect the HTML DOM structure and not the React component tree, features such as Context API and Event Bubbling continue to work as they did before.

To prevent event bubbling, as demonstrated in the example, you can use the [`stopPropagation()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation) method to ensure that only the event listener on the portal's container is triggered.

## Wrapping Up

Portals in React are a powerful feature that allows developers to render content outside of the normal component hierarchy. This can be useful for creating modals, popovers, and other UI elements that need to be positioned relative to a specific element or displayed on top of the main application interface.

When using portals, it's important to keep in mind some best practices.

* First, always make sure to clean up the portal node when the component unmounts. This can be done using the `useEffect` hook and the [`removeChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild) method.
    
* Second, be careful not to use portals excessively, as they can add unnecessary complexity to your code.
    
* Finally, always test your portals thoroughly for accessibility issues, as they can sometimes cause unexpected behaviour in certain browsers or screen readers. Ensure to follow the [WAI-ARIA Modal Authoring Practices](https://www.w3.org/WAI/ARIA/apg/#dialog_modal) when working with modals.
    

Thank you for reading! I hope you found this article helpful. If you did, kindly like and share it with your friends and colleagues :)

I would love to connect with you on [Twitter](https://twitter.com/israelmitolu) | [LinkedIn](https://www.linkedin.com/in/israeloyetunji/) | [Github](https://github.com/israelmitolu) | [Portfolio](https://israelmitolu.netlify.app/).

Happy coding!

## Resources

* [React Official Docs](https://react.dev/reference/react-dom/createPortal)
    
* [Web Dev Simplified: Learn React Portal in 12 Minutes By Building a Modal](https://www.youtube.com/watch?v=LyLa7dU5tp8)
    
* [Event Bubbling and Capturing in React](https://blog.logrocket.com/event-bubbling-capturing-react/)