An open API service indexing awesome lists of open source software.

https://github.com/richardscarrott/react-teleportal

Alternative React portal implementation, giving you control over portal rendering.
https://github.com/richardscarrott/react-teleportal

Last synced: 18 days ago
JSON representation

Alternative React portal implementation, giving you control over portal rendering.

Awesome Lists containing this project

README

        

# React Teleportal

[![GitHub package.json version](https://img.shields.io/github/package-json/v/richardscarrott/react-teleportal.svg)](https://www.npmjs.com/package/react-teleportal)
[![CI](https://github.com/richardscarrott/react-teleportal/actions/workflows/node.js.yml/badge.svg)](https://github.com/richardscarrott/react-teleportal/actions/workflows/node.js.yml)
[![GitHub license](https://img.shields.io/github/license/richardscarrott/react-teleportal.svg)](https://github.com/richardscarrott/react-teleportal/blob/main/LICENSE)

Alternative [React Portal](https://reactjs.org/docs/portals.html) implementation, giving you control over portal rendering.

Primarily written to support uninterrupted exit animations when combined with components such as [`TransitionGroup`](https://reactcommunity.org/react-transition-group/transition-group) and [`AnimatePresence`](https://www.framer.com/docs/animate-presence/).

## Install

```
npm install react-teleportal
```

## Examples

### React Teleportal x React Transition Group

https://codesandbox.io/s/react-teleportal-x-react-transition-group-k31d8p

### React Teleportal x Framer Motion

https://codesandbox.io/s/react-teleportal-x-framer-motion-766nu7

## Features

| Features | React Teleportal | ReactDOM.createPortal |
| --------------------------- | ---------------- | --------------------- |
| Custom Rendering | ✅ | ❌ |
| Context | ✅\* | ✅ |
| Server Side Rendering (SSR) | ⚠️† | ❌ |
| Multiple Portal Outlets | ❌‡ | ✅ |
| React Tree Event Bubbling | ❌ | ✅ |

\* Although ``s in React Teleportal don't receive context from their own call site, they do receive context from the `` call site which means context from root providers will be available.

† Unlike `ReactDOM.createPortal`, React Teleportal doesn't depend on DOM APIs so the intention is to support SSR once a concurrent-safe solution has been found.

‡ React Teleportal doesn't currently support multiple portal outlets, but it would be trivial to add. For now it's been omitted because it would effectively become a "slot" library which, as a pattern, [doesn't play nicely with streaming SSR](https://github.com/cloudflare/react-gateway/issues/49).

## API

### Basic

```tsx
import React, { useState } from 'react';
import { PortalProvider, PortalOutlet, Portal } from 'react-teleportal';

const App = () => {
const [show, setShow] = useState(true);
return (

setShow(!show)}>Toggle
{show ? (

<>I render in the PortalOutlet>

) : null}


);
};
```

### Animations with [react-transition-group](https://codesandbox.io/s/react-teleportal-x-react-transition-group-k31d8p)

```tsx
import React, { useState, useRef } from 'react';
import { PortalProvider, PortalOutlet, Portal } from 'react-teleportal';
import { TransitionGroup, CSSTransition } from 'react-transition-group';

const App = () => {
const [show, setShow] = useState(true);
const nodeRef = useRef(null);
return (

setShow(!show)}>Toggle
{show ? (


I render in the PortalOutlet



) : null}

{(children) => {children}}


);
};
```

### Animations with [framer-motion](https://codesandbox.io/s/react-teleportal-x-framer-motion-766nu7)

```tsx
import React, { useState } from 'react';
import { PortalProvider, PortalOutlet, Portal } from 'react-teleportal';
import { AnimatePresence, motion } from 'framer-motion';

const App = () => {
const [show, setShow] = useState(true);
return (

setShow(!show)}>Toggle
{show ? (


I render in the PortalOutlet


) : null}

{(children) => {children}}


);
};
```

## FAQ

### Does React Teleportal support SSR?

React Teleportal won't blow up on the server, but ``s won't be rendered to HTML server side and instead will be rendered once on the client.

The intention is to eventually find a concurrent-safe SSR solution.

### Can I have multiple _named_ ``s?

No not currently. React Teleportal intends to eventually support SSR & treating this as a "slot" library makes SSR less viable.

React Gateway is a good example of the "slot" pattern and [how it can easily fail if misused](https://github.com/cloudflare/react-gateway/issues/49).

```tsx
import { GatewayProvider, GatewayDest, Gateway } from 'react-gateway';

const App = () => {
return (






SSR will fail to render this as the "header-slot" has already rendered
(and if streaming, the html has potentially already been flushed to
the client).



);
};
```

React Teleportal is therefore stricter and only allows a single `` (or `` in React Teleportal terminology) which should be rendered at the _bottom_ of the root component.

### How do I manage stacking order?

It's recommended to avoid z-index and treat your `` similar to the DOM's [Top Layer](https://developer.chrome.com/blog/what-is-the-top-layer/) whereby the most recently ~~opened~~ mounted `` is rendered last and therefore naturally stacked on top.

### Why do I need to add a `key` to the `` child when animating?

The collective `` children are ultimately rendered as `children` of the `` which means React is rendering a variable length array of elements which [requires a `key`](https://beta.reactjs.org/learn/rendering-lists).

It's recommended to just statically include a `uuid` or similar at the call site of each distinct `` child to ensure it remains unique as your app grows.

```tsx

Hello World

```

> NOTE: If you're not animating (i.e. if the `` unmounts the child immediately), then you can omit the key as React Teleportal is able to assign a key on your behalf.

## License

[MIT](LICENSE)