react-portal-hook
Version:
A small react portal library made with hooks
156 lines (121 loc) • 3.08 kB
Markdown
# react-portal-hook
A small React portal library made with hooks. Allows you to render an indefinite number of portals without having to define them in advance. Useful for event-driven notifications or modals where you don't know how many items will be rendered at a given time.
## Getting Started
### Installation
To use react-portal-hook in your project, run:
```shell script
npm install react-portal-hook
```
### Setup
Wrap your root component with `PortalProvider`.
```jsx
// app.jsx
import { PortalProvider } from "react-portal-hook";
const App = () => {
return (
<PortalProvider>
<RootComponent />
</PortalProvider>
);
};
```
### Usage
**Example** - Modals:
By default, portals will be appended to `document.body`.
[Demo](https://codesandbox.io/s/react-portal-hook-modal-example-iow95)
```jsx
// page.jsx
import { usePortals } from "react-portal-hook";
const Modal = ({ closeModal }) => {
return (
<div>
<h2>Title</h2>
<p>This is a modal</p>
<button onClick={closeModal}>Close Modal</button>
</div>
);
};
export const Page = () => {
const portalManager = usePortals();
const openModal = () => {
portalManager.open(portal => <Modal closeModal={portal.close} />);
};
return (
<div>
<h2>Title</h2>
<p>This is a page</p>
<button onClick={openModal}>Open Modal</button>
</div>
);
};
```
**Example** - Notifications:
You can specify a DOM node in which to render portals with the `appendTo` option:
[Demo](https://codesandbox.io/s/react-portal-hook-notifications-example-os1b4)
```jsx
// layout.jsx
import { useRef } from "react";
import { usePortals } from "react-portal-hook";
const Notification = ({ closeNotification }) => {
return (
<div>
<p>
This is a notification{" "}
<button onClick={closeNotification}>Close Notification</button>
</p>
</div>
);
};
export const Layout = () => {
const portalManager = usePortals();
const notificationEl = useRef();
const showNotification = () => {
// Calling this from anywhere in your app will render a notification
portalManager.open(
portal => <Notification closeNotification={portal.close} />,
{
appendTo: notificationEl.current
}
);
};
return (
<div>
<div id="notification-holder" ref={notificationEl} />
<button onClick={showNotification}>Show Notification</button>
</div>
);
};
```
## API Documentation
#### `portalManager`
```typescript
interface PortalManager {
/**
* The react element you want to render in the portal
*/
element: ((portal: Portal) => React.ReactElement) | React.ReactElement;
options?: {
/**
* An ID to avoid duplicate portals
*/
id?: string;
/**
* A DOM node in which to render the portal
*/
appendTo?: Element;
/**
* A callback that is fired when the portal closes
*/
onClose?: () => void;
};
}
```
#### `Portal`
```typescript
interface Portal {
/**
* A function to close the Portal
*/
close: () => void;
}
```