Skip to content

oleystack/native-portal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

44 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

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