😎 🍒 React hook for Portals, which renders modals, dropdowns, tooltips etc. to <body> or else.
This is a React hook for Portals. It helps you render children into a DOM node that exists outside the DOM hierarchy of the parent component. From now on you will never need to struggle with modals, dropdowns, tooltips etc. Check the features section out to learn more. Hope you guys 👍🏻 it.
❤️ it? ⭐️ it on GitHub or Tweet about it.
⚡️ Try yourself: https://react-cool-portal.netlify.app
reactand
react-dom.
To use
react-cool-portal, you must use
[email protected]or greater which includes hooks.
This package is distributed via npm.
$ yarn add react-cool-portal # or $ npm install --save react-cool-portal
Here are some minimal examples of how does it work. You can learn more about it by checking the API out.
Inserts an element or component into a different location in the DOM.
import usePortal from "react-cool-portal";const App = () => { const { Portal } = usePortal();
return (
); };Wow! I am rendered outside the DOM hierarchy of my parent component.
By default, the children of portal is rendered into
of . You can specify the DOM element you want through thecontainerIdoption.import usePortal from "react-cool-portal";const App = () => { const { Portal } = usePortal({ containerId: "my-portal-root" });
return (
); };Now I am rendered into the specify element (id="my-portal-root").
Note: If the container element doesn't exist, we will create it for you.
Use with State
react-cool-portalprovides many useful features, which enable you to build a component with state. For instance, modal, dropdown, tooltip, and so on.import usePortal from "react-cool-portal";const App = () => { const { Portal, isShow, show, hide, toggle } = usePortal({ defaultShow: false, // The default visibility of portal, default is true onShow: (e) => { // Triggered when portal is shown // The event object will be the parameter of "show(e?)" }, onHide: (e) => { // Triggered when portal is hidden // The event object will be the parameter of "hide(e?)", it maybe MouseEvent (on clicks outside) or KeyboardEvent (press ESC key) }, });
return (
Open Modal Close Modal {isShow ? "Close" : "Open"} Modal); };Modal title
Modal body text goes here.
🧹 When no element in the container, we will remove it for you to avoid DOM mess.
The above example shows how easy you can handle the visibility of your component. You may ask how to handle the visibility with animations? No worries, you can disable the built-in
show/hidefunctions by setting theinternalShowHideoption tofalsethen handling the visibility of your component via theisShowstate.import usePortal from "react-cool-portal";const App = () => { const { Portal, isShow, show, hide, toggle } = usePortal({ defaultShow: false, internalShowHide: false, // Disable the built-in show/hide portal functions, default is true onShow: (e) => { // Triggered when "isShow" is set to true }, onHide: (e) => { // Triggered when "isShow" is set to false }, });
return (
Open Modal Close Modal {isShow ? "Close" : "Open"} Modal); };Modal title
Modal body text goes here.
Besides that, you can also handle the visibility of your component via React animation events or transition events like what I did for the demo app.
Build Your Customized Hook
Are you tired to write the same code over and over again? It's time to build your own hook based on
react-cool-portalthen use it wherever you want.import { useCallback } from "react"; import usePortal from "react-cool-portal";// Customize your hook based on react-cool-portal const useModal = (options = {}) => { const { Portal, isShow, ...rest } = usePortal({ ...options, defaultShow: false, internalShowHide: false, });
const Modal = useCallback( ({ children }) => (
{children}), [isShow] );return { Modal, isShow, ...rest }; };
// Use it wherever you want const App = () => { const { Modal, show, hide } = useModal();
return (
Open Modal Close Modal); };Modal title
Modal body text goes here.
One problem of the above example is that CSS transition/animation will be cut off due to the re-creating of the
Portalcomponent. So if you want to apply transitions or animations to the wrapped element of the customized hook. TheisShowneed to be passed from the props.const useModal = (options = {}) => { const { Portal, ...rest } = usePortal({ ...options, defaultShow: false, internalShowHide: false, });const Modal = useCallback( // Pass the "isShow" from props to prevent CSS transition/animation to be cut off ({ isShow, children }) => (
{children}), [] );return { Modal, ...rest }; };
API
const returnObj = usePortal(parameterObj);Return object
It's returned with the following properties.
| Key | Type | Default | Description | | ------ | --------- | ------- | ----------------------------------------------------------------------------------------------- | | Portal | component | | Renders children into a DOM node that exists outside the DOM hierarchy of the parent component. | | isShow | boolean |
false| The show/hide state of portal. | | show | function | | To show the portal or set theisShowtotrue. | | hide | function | | To hide the portal or set theisShowtofalse. | | toggle | function | | To toggle (show/hide) the portal or set theisShowtotrue/false. |Parameter object (optional)
When use
react-cool-portalyou can configure the following options via the parameter.| Key | Type | Default | Description | | ------------------ | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------------- | | containerId | string |
react-cool-portal| You can specify your own container id from an existing DOM element or let this hook automatically creates it for you. | | defaultShow | boolean |true| The initial show/hide state of the portal. | | clickOutsideToHide | boolean |true| Hide the portal by clicking outside of it. | | escToHide | boolean |true| Hide the portal by pressing ESC key. | | internalShowHide | boolean |true| Enable/disable the built-inshow/hideportal functions, which gives you a flexible way to handle your portal. | | onShow | function | | Triggered when portal is shown or theisShowset totrue. | | onHide | function | | Triggered when portal is hidden or theisShowset tofalse. |Contributors ✨
Thanks goes to these wonderful people (emoji key):
Welly
💻 📖 🚧
Dawid Karabin
📖
Honza Stepanovsky
🐛This project follows the all-contributors specification. Contributions of any kind welcome!