A simplified portal implementation for ⭕️ React Native ⭕️.
- Multi portals handling.
- Multi portal hosts handling.
- Allow override functionality.
- Compatible with
React Native Web
. - Compatible with
Expo
, check out the project Expo Snack. - Written in
TypeScript
.
yarn add @gorhom/portal
This is the very simple usage of this library, where you will teleport your content to the PortalProvider
layer of the app.
First, you will need to add PortalProvider
to your root component - this usually be the App.tsx
.
export const App = () => (
<PortalProvider>
{... your app goes here}
</PortalProvider>
);
Last, you wrap the content that you want to teleport with Portal
.
const BasicScreen = () => {
return (
{ ... }
<Portal>
<Text>
Text to be teleported to the root host
</Text>
</Portal>
{ ... }
);
};
This is when you need to teleport your content to a custom portal host PortalHost
at any layer in the app.
First, you will need to add PortalProvider
to your root component - this usually be the App.tsx
.
export const App = () => (
<PortalProvider>
{... your app goes here ...}
</PortalProvider>
);
Second, you will need to add PortalHost
at any layer in your app, with a custom name.
const CustomView = () => {
return (
{ ... }
<PortalHost name="CustomPortalHost" />
{ ... }
);
};
Last, you wrap the content that you want to teleport with Portal
and the custom portal host name.
const BasicScreen = () => {
return (
{ ... }
<Portal hostName="CustomPortalHost">
<Text>
Text to be teleported to the CustomView component
</Text>
</Portal>
{ ... }
);
};
In order to get your teleported content on top of all native views, you will need to wrap your content with FullWindowOverlay
from react-native-screens
.
import { FullWindowOverlay } from 'react-native-screens';
const BasicScreen = () => {
return (
{ ... }
<Portal>
<FullWindowOverlay style={StyleSheet.absoluteFill}>
<Text>
Text to be teleported to the CustomView component
</Text>
</FullWindowOverlay>
</Portal>
{ ... }
);
};
To avoid issues when using the React Native Portal with React Native Gesture Handler, you must place the PortalProvider
under the GestureHandlerRootView
, otherwise it might freeze your app.
export const App = () => (
<GestureHandlerRootView>
<PortalProvider>
{... your app goes here}
</PortalProvider>
</GestureHandlerRootView>
);
Read more about the app freezing issue.
Portal's key or name to be used as an identifer.
required:
NO |type:
string |default:
auto generated unique key
Host's key or name to teleport the portal content to.
required:
NO |type:
string |default:
'root'
Override internal mounting functionality, this is useful if you want to trigger any action before mounting the portal content.
type handleOnMount = (mount?: () => void) => void;
required:
NO |type:
function |default:
undefined
Override internal un-mounting functionality, this is useful if you want to trigger any action before un-mounting the portal content.
type handleOnUnmount = (unmount?: () => void) => void;
required:
NO |type:
function |default:
undefined
Portal's content.
required:
NO |type:
ReactNode | ReactNode[] |default:
undefined
Host's key or name to be used as an identifier.
required:
YES |type:
string
To access internal functionalities of all portals.
/**
* @param hostName host name or key.
*/
type usePortal = (hostName: string = 'root') => {
/**
* Register a new host.
*/
registerHost: () => void;
/**
* Deregister a host.
*/
deregisterHost: () => void;
/**
* Add portal to the host container.
* @param name portal name or key
* @param node portal content
*/
addPortal: (name: string, node: ReactNode) => void;
/**
* Update portal content.
* @param name portal name or key
* @param node portal content
*/
updatePortal: (name: string, node: ReactNode) => void;
/**
* Remove portal from host container.
* @param name portal name or key
*/
removePortal: (name: string) => void;
};
To keep this library maintained and up-to-date please consider sponsoring it on GitHub. Or if you are looking for a private support or help in customizing the experience, then reach out to me on Twitter @gorhom.