React portals are awesome! It's the feature that I'm not using frequently. But when I need it, I'm very glad I have the option to use it.
If you're reading this article, the chances are you need to use React portals yourself. And you've come to the right place. Because in this article, you're gonna learn everything there is to know about React portals.
You will learn:
- What is React portal
- How does React portal work
- How to use it in your project
Without any further ado, let's start with the portal itself. What it actually is?
Overview of React Portals
In this section, I'll explain in simple terms what React portals are. But first, let's look at the definition from the official source. Let's see what the React documentation is telling us.
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. (source: React)
The official definition is just spot on. It tells us exactly what React Portals are for.
React portals let us render component anywhere in the DOM. This makes it ideal to render floating components like modals, notifications, alerts, etc.
The usage of React portal is pretty simple as well. In order to render a component using React portal, all we need to do is following.
Using React portal
ReactDOM.createPortal(component, container)
createPortal
function takes 2 arguments:
- React component to render
- DOM container to render component into
Event Bubbling In React Portals
You may be wondering, if the elements is rendered outside of a parent component, does it behave differently somehow? Will the change in props
or state
of a parent triggers child to re-render?
Yes, it will!
As it is stated in the official documentation, component rendered using portals behaves the same way like any other component.
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 position in the DOM tree. (source: React)
All React features will work the samy way as they do without React portals. On top of that, event propagation won't change as well.
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. (source: React)
Common Use Cases of React Portals
Now you know whar React portals do. But you may be wondering, why do we need them? And the answer is simple. We need them if we want to render child component not directly in the parent component.
The most common use cases for React Portals are:
- Tooltips
- Modal dialogs
- Hover cards
- Loaders
No matter the use case, you should always keep these things in mind, when working with React portals:
- Events from child component will be proapgated to parent component.
- 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.
With all this in mind, we're ready to implement a simple component using React portals.
Using Portals in React
In this section, we'll take a look on how to use portals in React. We'll implement a simple Modal
component with the use of React Portals.
info
Full source code is available on Github.
Let's examine the top level component of our React app. The app is keeping track of the modal state. It contains a button that will trigger modal to open.
App.jsx
import { useState } from "react";
import Modal from "./components/Modal";
const App = () => {
const [showModal, setShowModal] = useState(false);
// Trigger modal to open
const openModal = () => setShowModal(true);
// Trigger modal to close
const closeModal = () => setShowModal(false);
return (
<main className="main">
<Modal
visible={showModal}
title="Portal Modal"
description="I was rendered usign portals"
onClose={closeModal}
/>
<button onClick={openModal}>Show Modal</button>
</main>
);
};
export default App;
Now, let's take a look at the Modal
component. That's where portal magic is happening.
import ReactDOM from "react-dom";
const Modal = ({ visible, title, description, onClose }) => {
const handleClick = (event) => event.stopPropagation();
// Don't render if visible equals false
if (!visible) return null;
return ReactDOM.createPortal(
<section className="overlay" onClick={onClose}>
<article className="modal" onClick={handleClick}>
<header>
<strong>{title}</strong>
</header>
<main>
<p>{description}</p>
</main>
</article>
</section>,
document.getElementById("root")
);
};
export default Modal;
Modal component consists of 2 main elements:
- Overlay that covers whole webpage
- Modal body that is rendered on the top of overlay
As you might guess, Modal
overlay should cover the whole screen, and for this reason, we don't want to display it inside the parent component. So we tell React to render it in #root
element.
This will produce teh following output.
note
Pay attention to the Elements
tab inside developer console. Do you see how overlay section
is rendered inside #root
element? Just like we specified using portal.
This was a very simple demostration of React portals. However, it showcase you how portals in React work. And using these principles, you can implement much more sophisticated components.
Concluding Thoughts
If you want to render REact component anywhere in DOM tree. React portals are definitely obvious choice. After all, they were designed to do such a thing.
In this article, we covered all there is to know about React portals. You learned why do we need them, how do they work, and what are common use cases for portals. In the last section, you also learned how to implement a component using portals.
Now, you have the solid understanding of React portals, and with all the information you just gained. You can start using them in React project.