Skip to content

oleystack/native-portal

Repository files navigation

@bit-about/native-portal

Bundle size

Install

npm i @bit-about/native-portal

Features

  • 100% Idiomatic React and 100% Typescript
  • Tiny & Efficient
  • Does not trigger unnecessary renderings
  • Just works β„’

Usage

import { portal } from '@bit-about/native-portal'

// 1️⃣ Create a portal
const Portal = portal()

// 2️⃣ Wrap your app with Provider
const App = () => (
  <Portal.Provider>
    {/* ... */}
  </Portal.Provider>
)

⬜ Set injection target

const ComponentA = () => (
  <>
    <Portal.Target />
  </>
)

πŸŒ€ ...then inject content from elsewhere

const ComponentB = () => (
  <>
    <Portal.Injector>
      <Text>Hello!</Text>
    </Portal.Injector>
  </>
)

Thanks to this, when the ComponentB is rendered, the Hello! sentence will be moved to the ComponentA.

Many portals under one provider

import { portal } from '@bit-about/native-portal'

// Declare destinations during portal creation
const Portal = portal('toHeader', 'toMenu', 'toHeaven')

⬜ Set injection target using name prop

const Menu = () => (
  <>
    <Portal.Target name="toMenu" />
  </>
)

πŸŒ€ ...then inject content using name prop

const Screen = () => (
    <>
      <Portal.Injector name="toMenu">
        <Text>{'New menu option'}</Text>
      </Portal.Injector>
    </>
  )

Default content

To declare fallback content for portal that is not in use, you can just pass children prop to Target component.

<Portal.Target>
  <Text>{'I am only visible when no content has been injected.'}</Text>
</Portal.Target>

Don't you like the default names?

import { portal } from '@bit-about/native-portal'

const {
  Provider: MyAmazingProvider,
  Target: MyAmazingTarget,
  Injector: MyAmazingInjector,
} = portal()

// ... and then

const App = () => (
  <MyAmazingProvider>
    {/* ... */}
  </MyAmazingProvider>
)

Common Questions

β–Ί What happens if I use multiple Injectors for one portal at the same time?

It works like a stack. The Target will render the latest content.
If the newest Injector is unmounted, the Target will render the previous one.

β–Ί What happens if I use multiple Targets for one portal at the same time?

Each Target will display the same content.

β–Ί Do I need to render Target before the Injectors?

Nope!
When you render Target it will be automatically filled up by the injected content.

β–Ί Is this efficient? What about the re-renders?

Yes.
Moreover, Providers and Injectors will be never unecessary re-rendered.
Target rerender only when the latest injected content changes.

Partners

wayfdigital.com

Credits

License

MIT Β© Maciej Olejnik πŸ‡΅πŸ‡±

Support me

Support me!

If you use my library and you like it...
it would be nice if you put the name BitAboutNativePortal in the work experience section of your resume.
Thanks πŸ™‡πŸ»!


πŸ‡ΊπŸ‡¦ Slava Ukraini