{"id":24084583,"url":"https://github.com/oleystack/native-portal","last_synced_at":"2026-06-09T04:33:37.245Z","repository":{"id":133220709,"uuid":"589819020","full_name":"oleystack/native-portal","owner":"oleystack","description":"🌀 Efficient Portals for React Native ","archived":false,"fork":false,"pushed_at":"2023-07-20T04:50:25.000Z","size":1267,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-22T04:03:49.803Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oleystack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-01-17T02:18:40.000Z","updated_at":"2023-03-11T16:58:19.000Z","dependencies_parsed_at":"2023-07-24T10:50:47.282Z","dependency_job_id":null,"html_url":"https://github.com/oleystack/native-portal","commit_stats":null,"previous_names":["oleystack/native-portal","bit-about/native-portal"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/oleystack/native-portal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleystack%2Fnative-portal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleystack%2Fnative-portal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleystack%2Fnative-portal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleystack%2Fnative-portal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oleystack","download_url":"https://codeload.github.com/oleystack/native-portal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleystack%2Fnative-portal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34092260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-10T00:38:12.247Z","updated_at":"2026-06-09T04:33:37.229Z","avatar_url":"https://github.com/oleystack.png","language":"TypeScript","funding_links":["https://github.com/sponsors/macoley"],"categories":[],"sub_categories":[],"readme":"\r\n\u003cp align=\"center\" style=\"font-weight: bold; font-size: 1.5em\"\u003e@bit-about/native-portal\u003c/p\u003e\r\n\u003cp align=\"center\"\u003e\r\n\u003ca href=\"https://www.npmjs.com/package/@bit-about/native-portal\"\u003e\u003cimg alt=\"\" src=\"https://img.shields.io/npm/v/@bit-about/native-portal.svg\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://bundlephobia.com/package/@bit-about/native-portal\"\u003e\u003cimg alt=\"Bundle size\" src=\"https://img.shields.io/bundlephobia/minzip/@bit-about/native-portal?label=size\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://codecov.io/gh/bit-about/native-portal\"\u003e\u003cimg alt=\"\" src=\"https://img.shields.io/codecov/c/github/bit-about/native-portals?token=BuGi92VqnL\" /\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\r\n## Install\r\n\r\n```bash\r\nnpm i @bit-about/native-portal\r\n```\r\n\r\n## Features\r\n\r\n- 100% **Idiomatic React** and 100% Typescript\r\n- Tiny \u0026 Efficient\r\n- Does not trigger unnecessary renderings\r\n- **Just works** ™\r\n\r\n## Usage\r\n\r\n```tsx\r\nimport { portal } from '@bit-about/native-portal'\r\n\r\n// 1️⃣ Create a portal\r\nconst Portal = portal()\r\n\r\n// 2️⃣ Wrap your app with Provider\r\nconst App = () =\u003e (\r\n  \u003cPortal.Provider\u003e\r\n    {/* ... */}\r\n  \u003c/Portal.Provider\u003e\r\n)\r\n\r\n```\r\n\r\n\r\n⬜ Set injection target\r\n```tsx\r\nconst ComponentA = () =\u003e (\r\n  \u003c\u003e\r\n    \u003cPortal.Target /\u003e\r\n  \u003c/\u003e\r\n)\r\n```\r\n\r\n\r\n🌀 ...then inject content from elsewhere\r\n```tsx\r\nconst ComponentB = () =\u003e (\r\n  \u003c\u003e\r\n    \u003cPortal.Injector\u003e\r\n      \u003cText\u003eHello!\u003c/Text\u003e\r\n    \u003c/Portal.Injector\u003e\r\n  \u003c/\u003e\r\n)\r\n```\r\n\r\nThanks to this, \r\nwhen the `ComponentB` is rendered, \r\nthe `Hello!` sentence will be moved to the `ComponentA`.\r\n\r\n## Many portals under one provider\r\n```tsx\r\nimport { portal } from '@bit-about/native-portal'\r\n\r\n// Declare destinations during portal creation\r\nconst Portal = portal('toHeader', 'toMenu', 'toHeaven')\r\n```\r\n\r\n⬜ Set injection target using `name` prop\r\n```tsx\r\nconst Menu = () =\u003e (\r\n  \u003c\u003e\r\n    \u003cPortal.Target name=\"toMenu\" /\u003e\r\n  \u003c/\u003e\r\n)\r\n```\r\n\r\n\r\n🌀 ...then inject content using `name` prop\r\n```tsx\r\nconst Screen = () =\u003e (\r\n    \u003c\u003e\r\n      \u003cPortal.Injector name=\"toMenu\"\u003e\r\n        \u003cText\u003e{'New menu option'}\u003c/Text\u003e\r\n      \u003c/Portal.Injector\u003e\r\n    \u003c/\u003e\r\n  )\r\n```\r\n\r\n\r\n## Default content\r\nTo declare fallback content for portal that is not in use, you can just pass `children` prop to `Target` component.\r\n\r\n```tsx\r\n\u003cPortal.Target\u003e\r\n  \u003cText\u003e{'I am only visible when no content has been injected.'}\u003c/Text\u003e\r\n\u003c/Portal.Target\u003e\r\n```\r\n\r\n## Don't you like the default names?\r\n```tsx\r\nimport { portal } from '@bit-about/native-portal'\r\n\r\nconst {\r\n  Provider: MyAmazingProvider,\r\n  Target: MyAmazingTarget,\r\n  Injector: MyAmazingInjector,\r\n} = portal()\r\n\r\n// ... and then\r\n\r\nconst App = () =\u003e (\r\n  \u003cMyAmazingProvider\u003e\r\n    {/* ... */}\r\n  \u003c/MyAmazingProvider\u003e\r\n)\r\n```\r\n\r\n## Common Questions\r\n##### ► What happens if I use multiple `Injectors` for one portal at the same time?\r\nIt works like a stack. The `Target` will render the latest content. \u003cbr/\u003eIf the newest `Injector` is unmounted, the `Target` will render the previous one.\r\n\r\n##### ► What happens if I use multiple `Targets` for one portal at the same time?\r\nEach `Target` will display the same content.\r\n\r\n##### ► Do I need to render `Target` before the `Injectors`?\r\nNope! \u003cbr/\u003e\r\nWhen you render `Target` it will be automatically filled up by the injected content.\r\n\r\n##### ► Is this efficient? What about the re-renders?\r\nYes. \u003cbr/\u003e\r\nMoreover, `Providers` and `Injectors` will be never unecessary re-rendered.\u003cbr/\u003e\r\n`Target` rerender only when the latest injected content changes.\r\n\r\n## Partners  \r\n\u003ca href=\"https://www.wayfdigital.com/\"\u003e\u003cimg alt=\"wayfdigital.com\" width=\"100\" height=\"100\" src=\"https://user-images.githubusercontent.com/1496580/161037415-0503f763-a60b-4d40-af9f-95d1304fa486.png\"/\u003e\u003c/a\u003e\r\n\r\n## Credits\r\n- [use-context-selector](https://github.com/dai-shi/use-context-selector) \u0026 [FluentUI](https://github.com/microsoft/fluentui) - fancy re-render avoiding tricks and code main inspiration\r\n\r\n## License\r\nMIT © [Maciej Olejnik 🇵🇱](https://github.com/macoley)\r\n\r\n## Support me \r\n\r\n\u003ca href=\"https://github.com/sponsors/macoley\"\u003e\u003cimg alt=\"Support me!\" src=\"https://img.shields.io/badge/github.com-Support%20me!-green\"/\u003e\u003c/a\u003e\r\n\r\nIf you use my library and you like it...\u003cbr /\u003e\r\nit would be nice if you put the name `BitAboutNativePortal` in the work experience section of your resume.\u003cbr /\u003e\r\nThanks 🙇🏻! \r\n\r\n\r\n---\r\n\u003cp align=\"center\"\u003e🇺🇦 Slava Ukraini\u003c/p\u003e\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleystack%2Fnative-portal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foleystack%2Fnative-portal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleystack%2Fnative-portal/lists"}