⚠️ This library is in-progress, API might changed rapidly. I don't recommend to use it now. If you'd like to give it a try, please follow the release note for any change. Here's the milestone.
React Cool Portal
This is a React hook for Portals. It helps you render an element outside of its component hierarchy. From now on you will never need to struggle with modals, dropdowns, tooltips etc. Hope you guys 👍🏻 it.
❤️ it? ⭐️ it on GitHub or Tweet about it.


⚡️ Try yourself: https://react-cool-portal.netlify.com
Milestone
Requirement
To use react-cool-portal
, you must use react@16.8.0
or greater which includes hooks.
Installation
This package is distributed via npm.
$ yarn add react-cool-portal
$ npm install --save react-cool-portal
Usage
Basic Use Case
Inserts an element or component into the a different location in the DOM.
import React from 'react';
import usePortal from 'react-cool-portal';
const App = () => {
const { Portal } = usePortal();
return (
<div>
<Portal>
<div>
Wow! I am rendered outside the DOM hierarchy of my parent component.
</div>
</Portal>
</div>
);
};
By default, the children of the Portal
is rendered into <div id="react-cool-portal">
of <body>
. You can use your own container element by the containerId
option.
import React from 'react';
import usePortal from 'react-cool-portal';
const App = () => {
const { Portal } = usePortal({ containerId: 'my-portal-root' });
return (
<div>
<Portal>
<div>Now I am rendered into the "my-portal-root" element.</div>
</Portal>
</div>
);
};
Note: If the container element doesn't exist, we will create it for you.
Use with State
react-cool-portal
provides many useful features, which enable you to build a component with state like modal, dropdown, tooltip and so on.
import React from 'react';
import usePortal from 'react-cool-portal';
const App = () => {
const { Portal, isShow, show, hide, toggle } = usePortal({
containerId: 'my-portal-root',
defaultShow: false,
clickOutsideToHide: true,
escToHide: true,
onShow: e => {
},
onHide: e => {
}
});
return (
<div>
<button onClick={show}>Open Modal</button>
<button onClick={hide}>Close Modal</button>
<button onClick={toggle}>{isShow ? 'Close' : 'Open'} Modal</button>
<Portal>
<div class="modal-backdrop" tabIndex={-1}>
<div
class="modal"
role="dialog"
aria-labelledby="modal-label"
aria-modal="true"
>
<div class="modal-header">
<h5 id="modal-label" class="modal-title">
Modal title
</h5>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
</div>
</div>
</Portal>
</div>
);
};
♻️ When no element in the container, we will auto remove it for you. Therefore, doesn't produce DOM mess.
Contributors ✨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!