What is react-portal?
The react-portal package allows you to render components into a DOM node that exists outside the DOM hierarchy of the parent component. This is useful for creating modals, tooltips, and other UI elements that need to be rendered outside the main document flow.
What are react-portal's main functionalities?
Basic Portal Usage
This example demonstrates the basic usage of the react-portal package. It renders a div element outside the main DOM hierarchy, which can be useful for creating modals or tooltips.
import React from 'react';
import ReactDOM from 'react-dom';
import { Portal } from 'react-portal';
function App() {
return (
<div>
<h1>Main App</h1>
<Portal>
<div style={{ position: 'absolute', top: '50px', left: '50px', background: 'white', border: '1px solid black', padding: '10px' }}>
This is a portal content
</div>
</Portal>
</div>
);
}
export default App;
Custom Portal Target
This example shows how to use a custom DOM node as the target for the portal. The content will be rendered inside the specified custom target element.
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import { Portal } from 'react-portal';
function App() {
const customTarget = useRef(null);
return (
<div>
<h1>Main App</h1>
<div ref={customTarget} id="custom-target" style={{ position: 'relative', height: '200px', border: '1px solid black' }}>
Custom Target
</div>
<Portal node={customTarget.current}>
<div style={{ position: 'absolute', top: '10px', left: '10px', background: 'white', border: '1px solid black', padding: '10px' }}>
This is a portal content inside custom target
</div>
</Portal>
</div>
);
}
export default App;
Other packages similar to react-portal
react-dom
The react-dom package provides the createPortal function, which allows you to render children into a DOM node that exists outside the DOM hierarchy of the parent component. It is a part of the React core library and offers similar functionality to react-portal.
react-reverse-portal
The react-reverse-portal package allows you to create portals that can be moved around in the DOM. It provides more advanced features compared to react-portal, such as the ability to move portals between different parts of the DOM dynamically.
react-teleport
The react-teleport package offers a simple API for rendering components outside the main DOM hierarchy. It is similar to react-portal but provides additional features like teleporting components to different parts of the DOM based on conditions.
React-portal
Struggling with modals, lightboxes or loading bars in React? React-portal creates a new top-level React tree and injects its children into it. That's necessary for proper styling (especially positioning).
Looking for v3 documentation? Go here.
Features
- uses React v16 and its official API for creating portals
- has a fallback for React v15
- transports its children into a new React Portal which is appended by default to document.body
- can target user specified DOM element
- supports server-side rendering
- supports returning arrays (no wrapper divs needed)
<Portal />
and <PortalWithState />
so there is no compromise between flexibility and convenience- doesn't produce any DOM mess
- provides close on ESC and close on outside mouse click out of the box
- no dependencies, minimalistic
Installation
yarn add react react-dom react-portal
Usage
Portal
import { Portal } from 'react-portal';
<Portal>
This text is portaled at the end of document.body!
</Portal>
<Portal node={document && document.getElementById('san-francisco')}>
This text is portaled into San Francisco!
</Portal>
That's it! Do you want to toggle portal? It's a plain React component, so you can simply do:
{isOpen && <Portal>Sometimes portaled?</Portal>}
This gives you absolute flexibility and control and I would recommend you to use it as a basic building block for your components like modals or notifications. This code also works with server-side rendering. If you think about just using official ReactDOM.createPortal()
, you would have to check for existence of DOM environment.
React-portal used to come packed with some extra goodies because sometimes you are ok with giving up some flexibility for convenience. For that case, V4 introduces another component that handles its own state for you:
PortalWithState
import { PortalWithState } from 'react-portal';
<PortalWithState closeOnOutsideClick closeOnEsc>
{({ openPortal, closePortal, isOpen, portal }) => (
<React.Fragment>
<button onClick={openPortal}>
Open Portal
</button>
{portal(
<p>
This is more advanced Portal. It handles its own state.{' '}
<button onClick={closePortal}>Close me!</button>, hit ESC or
click outside of me.
</p>
)}
</React.Fragment>
)}
</PortalWithState>
Don't let this example intimidate you! PortalWithState
expects one child, a function. This function gets a few parameters (mostly functions) and returns a React component.
There are 4 optional parameters:
- openPortal - function that you can call to open the portal
- closePortal - function that you can call to close the portal
- portal - the part of component that should be portaled needs to be wrapped by this function
- isOpen - boolean, tells you if portal is open/closed
<PortalWithState />
accepts this optional props:
- node - same as
<Portal>
, you can target a custom DOM element - closeOnOutsideClick - boolean, portal closes when you click outside of it
- closeOnEsc - boolean, portal closes when the ESC key is hit
- defaultOpen - boolean, the starting state of portal is being open
- onOpen - function, will get triggered after portal is open
- onClose - function, will get triggered after portal is closed
Also notice, that the example returns a Fragment since React 16.2 supports it! You can also return:
- an array - available from React v16, remember to add
key
attribute - regular component - the example would be wrapped by a div, not a fragment
If you start running into limits of <PortalWithState />
(complex animations), you probably want to use <Portal />
instead and build a component tailored to your specific taste.
Run Examples
git clone https://github.com/tajo/react-portal
cd react-portal
yarn install
yarn build:examples
open examples/index.html
Contributions Welcome!
git clone https://github.com/tajo/react-portal
cd react-portal
yarn install
yarn build:examples --watch
open examples/index.html
Run Tests
yarn test
Author
Vojtech Miksu 2017, miksu.cz, @vmiksu