DEV Community

Cover image for React Portals Explained: A Guide for Developers
Anagha GN
Anagha GN

Posted on

React Portals Explained: A Guide for Developers

React Portals provide an advanced capability in React, enabling developers to render components outside the main React component hierarchy. This functionality is particularly useful for creating modals, tooltips, and other elements that need to exist outside their parent component’s DOM structure. By leveraging portals, developers can achieve more flexible and robust user interface designs, enhancing the overall user experience.

In this article, we will delve into React Portals, examining their functionality and demonstrating how to utilize them effectively within your React applications.

Introduction to React Portals
React Portals offer a solution for rendering components into a DOM node that exists outside the usual component hierarchy. Typically, rendering a component in React inserts it as a child within its parent component’s DOM structure. However, there are cases, such as creating modals or dropdown menus, where it is necessary to render a component elsewhere in the DOM.

React Portals address this by allowing a component’s output to be rendered in a different DOM node, outside of its parent component’s DOM hierarchy. This approach enables the visual display of components at any location within the DOM while maintaining their logical position in the React component tree.

This functionality is made possible by a feature in react-dom called “portals.” The react-dom library provides a createPortal method, which takes two arguments: the content to be rendered (referred to as children) and the target DOM node where the content should be rendered, as demonstrated below:

`import {createPortal} from 'react-dom';
createPortal(children, domNodeContainer);`
Enter fullscreen mode Exit fullscreen mode

Some use cases for React Portals include:

  1. Modal Dialogs: Modals often need to overlay the entire page, requiring them to be rendered outside the current component hierarchy to ensure they appear above all other content. React Portals facilitate the rendering of modal components outside their parent components, simplifying the management of their visibility and behavior.

  2. Tooltips and Popovers: These components usually need to be displayed near a specific element or at a certain position on the page. React Portals allow you to render tooltips and popovers in a different part of the DOM, enabling precise positioning relative to the triggering element.

  3. Dropdown Menus: To ensure correct positioning and layering, dropdown menus must often be rendered outside their parent component. React Portals make it easy to render dropdown menus outside the regular component hierarchy, while still maintaining their interaction with the triggering elements.

Benefits of using React Portals
React Portals provide several advantages when building React applications, including:

1. Versatile Component Placement: React Portals enable components to be rendered anywhere in the DOM, outside the usual component hierarchy. This offers greater flexibility for creating complex UIs and precisely positioning components as needed.

2. Separation of Visual and Logical Concerns: Portals allow the visual display of a component to be separated from its logical position in the component tree. This improves code organization and makes the codebase easier to understand and maintain.

3. Reduced CSS Conflicts: By rendering components through portals, their styles are isolated from parent and sibling components. This helps to prevent CSS conflicts, ensuring that the styles of portal components remain unaffected by the surrounding environment.

4. Improved Accessibility: Portals are particularly useful for creating accessible components, such as modals. By rendering them at the top level of the DOM, they become more accessible to screen readers and assistive technologies, enhancing the overall accessibility of the application.

5. Seamless Integration with Third-Party Libraries: React Portals make it easier to integrate third-party libraries or components that need to be rendered outside the main React hierarchy. This allows external functionalities to be incorporated seamlessly while maintaining the integrity of the React application.

6. Enhanced Performance: React Portals can boost application performance by reducing unnecessary re-renders. Since portal components are rendered outside the regular component hierarchy, they can be updated independently, minimizing the need for re-renders throughout the entire application.

How to implement React Portals?
To illustrate the functionality of React Portals, let’s build an example using a modal.

Create React application

`npm create vite@latest
Need to install the following packages:
create-vite@5.4.0
Ok to proceed? (y) y
✔ Project name: … sample-react-portal
✔ Select a framework: › React
✔ Select a variant: › JavaScript`
Enter fullscreen mode Exit fullscreen mode

Now, we will develop an application component that includes a button element and a modal component. The modal will be displayed only when the button is clicked.

App.jsx

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

function App() {
 const [isOpen, setOpen] = useState(false);
 return (
  <div>
   <button
    onClick={() => {
     setOpen(true);
    }}>
    Open
   </button>
   <Modal isOpen={isOpen} onClose={() => setOpen(false)} />
  </div>
 );
}
export default App;`
Enter fullscreen mode Exit fullscreen mode

The provided code defines an App component that includes a button for toggling the visibility of a modal component. The display of the modal is controlled by the isOpen state variable. When the button is clicked, the modal appears. The modal can be closed by invoking the onClose function, which updates the state to hide the modal.

modal.jsx

`import React from 'react';
import { createPortal } from 'react-dom';
import './modal.css';

export default function Modal({ isOpen, onClose }) {
 if (!isOpen) return null;
 return createPortal(
  <div className='modal'>
   <div className='modal-container'>
    <div className='modal-body'>
     <p>Sample Modal</p>
    </div>
    <button onClick={onClose}>Close</button>
   </div>
  </div>,
  document.getElementById('modal') // this instructs `react-dom` to render the modal outside the current React component hierarchy.
 );
}`
Enter fullscreen mode Exit fullscreen mode

The modal component is designed to accept two props: isOpen and onClose. The isOpen prop determines the visibility of the modal, while the onClose prop is a callback function that gets invoked to close the modal.

When the isOpen prop is set to false, the modal is not rendered, and the component returns null, meaning no content is displayed.

When the isOpen prop is true, the component utilizes the createPortal function to render the modal content outside the current React component hierarchy. The createPortal function takes two arguments: the JSX code representing the modal and the target DOM element where the modal should be rendered. In this scenario, the target DOM element is specified as document.getElementById(‘modal’). This instructs react-dom to render the modal within the DOM element with the ID modal, effectively positioning it outside the normal React component tree.

index.html

To proceed, open the index.html file. You’ll find a div element with the ID root. This element serves as the container for all React-rendered content.

In the main.jsx file (for Vite) or the index.js file (for Create React App), you’ll observe that react-dom references this root element. It constructs a new DOM structure dedicated to React components and renders each component within this structure.

For our project, modify the index.html file by adding another div element with the ID modal. This will serve as the target for rendering our modal component outside the main React component tree.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sample React Portal</title>
  </head>
  <body>
    <div id="root"></div>
    <div id="modal"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>modal.css
Enter fullscreen mode Exit fullscreen mode

Let’s apply some basic styling to our modal:

modal.css

p {
 color: black;
}
.modal {
 position: fixed;
 z-index: 2;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 background-color: rgba(0, 0, 0, 0.5);
 overflow: auto;
}
.modal-container {
 background-color: #fefffe;
 margin: 10% auto;
 width: 50%;
 padding: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Now, let’s start the server to view the components in action. Execute the following command and open the URL [http://127.0.0.1:5173/] in your browser:

`npm run dev`
Enter fullscreen mode Exit fullscreen mode

Output:

Image description
React Portal Example

We can see that the button element is rendered within the main root container, representing the primary container for the entire React application. However, the modal component, despite being defined within the parent App component, is rendered in a separate target location in the DOM, typically outside the regular React component tree.

In our code, the modal component is a child of a div element within the App component, which is centrally located in the root container. React Portals enable us to define the modal component within the App component while rendering it in a different part of the DOM, outside the regular React tree structure. This functionality allows us to pass values to the modal’s props and render content within the modal component effectively.

Important Considerations and Potential Issues

React Portals offer valuable capabilities, but there are several important factors to consider:

1. Target DOM Nodes: When utilizing portals, ensure the target DOM node exists within the document. If the target node is missing, it can lead to errors or unintended behavior. It is prudent to confirm the presence of the target node before attempting to render portal content.

2. Event Propagation: Events emitted from a portal component will, by default, bubble up through the React tree and may trigger event handlers on parent components. This default behavior might not always be desirable. To control event propagation and limit event handling to within the portal, consider using stopPropagation() or other event management techniques.

3. Styling Challenges: Since portal components are rendered outside the standard React component hierarchy, applying CSS can be tricky. Styles that depend on parent-child relationships might not behave as expected. It is advisable to use specific CSS selectors or scoped styling to ensure that portal components are styled correctly.

4. Performance Considerations: React Portals can enhance performance in certain scenarios, but they can also introduce overhead. For instance, rendering a large list of items (e.g., 1,000 entries) through a portal requires two render passes: one for the virtual DOM and another for the actual DOM. This additional rendering step can impact performance, particularly with large amounts of content. To avoid performance issues, use portals selectively and only when necessary.

React Portals offer a robust solution for rendering components outside their parent component hierarchy, enabling the creation of complex and flexible user interfaces by placing components at any location within the DOM. Utilizing portals can help with separating concerns, enhancing accessibility, and providing greater adaptability in developing React applications.
To ensure effective use and avoid potential pitfalls, it is essential to adhere to the considerations and best practices outlined in this guide. With careful application, React Portals can significantly expand the capabilities of your React applications and improve the overall user experience.
Take advantage of React Portals to craft dynamic, interactive, and visually engaging components in your React projects.

Top comments (0)