Let’s take a look at Portals – the handy way to get your component from A to B!
What are Portals?
Portals are a way to render a component as a child of a DOM node outside of the parent component.
What problem do Portals solve?
Portals help to solve the problem of working in a React way by building self-sufficient / independent components while still creating semantically-correct code.
A good example is when creating a modal. If you were working in a React, component-focused way, you might group together your background overlay and modal window within a component and then nest that component within another one (say your App
component).
However, if you were working with pure HTML, CSS and JS, you more than likely wouldn’t dream of nesting your modal within anything other than the <body>
. After all, a modal is designed to show on top of all other content, so it should probably be the first element in your page. This would be the more semantically-appropriate and accessible way of writing your HTML.
So, as you can see, we’ve got a clash of best practices. Portals help to solve that issue.
How do Portals work?
The name is pretty accurate; you create a portal through to another place in your React app and send your component through it to be rendered at the destination.
First, determine the destination of the component you want to portal. This could be a simple container <div>
in your index.html
file.
Then, import ReactDOM and use the createPortal()
method to send the component through. createPortal()
takes two arguments:
- The React node (the component) you want to send through the portal to render on the other end. This should be JSX code.
- The destination; a node in the real DOM.
Example of Portal usage
Let’s say you had the following in your index.html
file which came immediately after your opening <body>
tag. This is outside of the #root
element where you render your main App
component with ReactDOM.createRoot()
.
<div id="portal-test"></div>
The PortalExample
component in the code below implements createPortal()
to render the PortalChild
component as a child of the <div>
from the index.html
file above.
import React, { Fragment } from "react";
import ReactDOM from "react-dom";
const PortalChild = (props) => {
return (
<div>
<p>
This PortalChild component is portaled from the PortalExample component.
</p>
</div>
);
};
const PortalExample = (props) => {
return (
<Fragment>
<h2>Portal Component Example</h2>
{ReactDOM.createPortal(
<PortalChild />,
document.getElementById("portal-test")
)}
</Fragment>
);
};
export default PortalExample;