What are Portals in React?
`Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component, allowing it to maintain the properties and behaviors it inherited from the React tree`
The Portal's most common use cases are when the child components need to visually break out of the parent container. Most of the cases i implemented one was together with Modals. Of course i am going to give a very simple example how to implement one.
Implementing a Portal is very easy.
Step 1:
Inside the index.html file that is located in the public folder, add a new div with a ID as you wish for our modal to be rendered.
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- this is the new div to render our modal component -->
<div id="modal"></div>
</body>
Step 2:
In your App.js we are going to implement a count to see if the props and functionality is passed through the different nodes in our app. And of course i am going to pass the other functions to update our count and open / close the modal. First we need to grab our new ID we added above and we will create it with a simple method from reactDOM.. ReactDOM.createPortal(child, container).
import React, { useState } from "react";
import Modal from "./Modal";
const App = () => {
const [open, setOpen] = useState(false);
const [count, setCount] = useState(0);
return (
<div>
<div>Outside Modal</div>
<div>{count}</div>
<button onClick={() => setOpen(true)}>Open Modal</button>
<Modal open={open} setOpen={setOpen} setCount={setCount} />
</div>
);
};
export default App;
Step 3:
And now create a new file Modal.jsx that will be basically our component that will be rendered in out new Node, outside of the react component hierarchy. The portal will be created as noted above with ReactDOM.createPortal():
import React from "react";
import ReactDOM from "react-dom";
const reactModal = document.getElementById("modal");
const Modal = ({ open, setOpen, setCount }) => {
const OVERLAY_CONATINER = {
zIndex: 1000,
backgroundColor: "rgba(0,0,0,0.3)",
width: 400,
height: 200,
position: "fixed",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
padding: "50px",
};
const countHandler = () => {
setCount((prev) => prev + 1);
};
return ReactDOM.createPortal(
<>
<div>
{open && (
<div style={OVERLAY_CONATINER}>
<span>Inside Modal</span>
<button onClick={() => setOpen(false)}> Close Modal</button>
<button onClick={countHandler}>Increment Count</button>
</div>
)}
</div>
</>,
reactModal
);
};
export default Modal;
Open your development tools and In the root we see only the elements located outside the Portal in App.js.
If you close the modal, nothing will be rendered in out "modal" div.
If you click the Increment button, you will see that everything works in the right way, meaning that the connection exists between those 2 nodes. Of course i tried to keep it as simple as possible, but you can try to add maybe some more functionality for testing and some styles when open the Modal.
Portals are extremely useful when we need to implement a Modal as shown here, or Loaders, or even Tooltips in our App.