{"id":27240648,"url":"https://github.com/zenyr/react-native-portal","last_synced_at":"2025-04-10T19:45:15.649Z","repository":{"id":20117228,"uuid":"88840688","full_name":"zenyr/react-native-portal","owner":"zenyr","description":"(deprecated) Trans-locate your render destination, using mitt. Built with react@16 and react-native in mind.","archived":false,"fork":false,"pushed_at":"2023-01-25T23:13:53.000Z","size":818,"stargazers_count":69,"open_issues_count":19,"forks_count":15,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T07:20:44.880Z","etag":null,"topics":["mitt","react","react-native"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/zenyr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-20T08:35:08.000Z","updated_at":"2023-05-11T17:56:29.000Z","dependencies_parsed_at":"2023-02-14T12:10:18.395Z","dependency_job_id":null,"html_url":"https://github.com/zenyr/react-native-portal","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenyr%2Freact-native-portal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenyr%2Freact-native-portal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenyr%2Freact-native-portal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenyr%2Freact-native-portal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zenyr","download_url":"https://codeload.github.com/zenyr/react-native-portal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248055273,"owners_count":21040152,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["mitt","react","react-native"],"created_at":"2025-04-10T19:45:15.020Z","updated_at":"2025-04-10T19:45:15.639Z","avatar_url":"https://github.com/zenyr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-native-portal\n\n[![npm version](https://badge.fury.io/js/react-native-portal.svg)](https://badge.fury.io/js/react-native-portal) [![Build Status](https://travis-ci.com/zenyr/react-native-portal.svg?branch=master)](https://travis-ci.com/zenyr/react-native-portal)\n\nTranslocate your render destination. Using [`mitt`](https://npm.im/mitt). Built with `react@16` and `react-native` in mind, but these are not strictly required, as long as `React.PureComponent` is available.\n\nThe code itself is very minimal and only rely on react's `context`, and written in `ES6`.\n\nFeel free to file an issue/PR if you have a better way to publish this component.\n\n# Live demo on web\n\n- Although I built this module for `react-native`, it works just as great on web.\n- https://codepen.io/zenyr/pen/xLrKPZ\n\n# Aim of this project\n\n- Minimalistic API\n- Minimal dependancy\n- Use official react API only\n\n# Known issues\n\n- Try not to put falsy `0` or `''` through. ( ͡° ͜ʖ ͡°)\n- A behavior of `BlackPortal`s having the exact same `name` is undefined, yet.\n  - Ideas appreciated\n- Uncanny resemblance with [cloudflare/react-gateway](https://github.com/cloudflare/react-gateway)\n  - This one is smaller though\n- Has `react-native` in its name but works on anywhere including browser DOM.\n- (webpack only) needs proper babel configuration (see **ES6 usage** and **ES5 usage** below)\n\n# Install\n\n1. install npm module\n```\nnpm i react-native-portal -P\nor\nyarn add react-native-portal --prod\n```\nMake sure to put `-P` or `--prod` to ignore useless packages for consuming this module.  \nIt should automatically install `mitt`, only if necessary.\n\n2. Wrap your root component with `PortalProvider`.  \nAs it requires a single child it is *reasonable* to wrap it in your **entry file**.\n```js\nimport {PortalProvider} from 'react-native-portal'\n...\nrender(\u003cPortalProvider\u003e\u003cYourApp /\u003e\u003c/PortalProvider\u003e, document.querySelector('#app'))\n```\n\n3. Put your WhitePortal and BlackPortal as you wish, matching their `name` props.\n4. Enjoy your inner peace 🙏\n\n## ES5 usage\n\nYou *can* access this module on `react-dom` + legacy browser environment via unpkg.  \nGood enough for quick prototyping and goofying around.\n\n```\nhttps://unpkg.com/react-native-portal/dist/es5.js\nhttps://unpkg.com/react-native-portal/dist/min.js\n  (expects React global, prop-types \u0026 mitt bundled)\n```\n\nHowever I do not recommend this on production 😂\n\n## ES6 usage (outside of `react-native`)\n\nOnly refer this if you are going to use this module on browsers or a modified environment.  \n\u003cdetails\u003e\n\u003csummary\u003eSolution 1. Vanilla es6 module\u003c/summary\u003e\n\n  Since 1.1.1 I've included `dist/noflow.js` in the npm repo.\n  It sticks to the pure es6 spec (as of es2015) so you won't need to strip away class properties and flow comments.\n\n  ```js\n  import {PortalProvider} from 'react-native-portal/dist/noflow';\n  ```\n\n  (I'd better improve those filenames. I'll do a major semver update in that case!)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSolution 2. Babel config\u003c/summary\u003e\n  This module will work out-of-the-box with most React-native configurations. But you may need to tweak a few options to use `react-native-portal`.\n\n```js\n  module: {\n    rules: [\n      ...\n      {\n        test: /\\.js$/,\n        exclude: {\n          and: [\n            /(node_modules|bower_components)/, // \u003c\u003c Note 1\n            { not: [/(react-native-portal)/] }, // \u003c\u003c Note 2\n          ],\n        },\n        use: {\n          loader: 'babel-loader',\n          options: {\n            presets: [\n              ...        \n            ],\n            plugins: [\n              ...,\n              ['transform-class-properties', { spec: false }], // \u003c\u003c\u003c Note 3. `spec` is optional\n              ['transform-flow-strip-types'], // \u003c\u003c\u003c Note 4. Only if you are NOT using flow\n            ],\n          },\n        },\n      },\n    },\n    ...\n  }\n```\n\n  Above snippet from `webpack.config.js` has 3 lines that you may have to set up properly with `babel-loader`.\n\n  1. It is advised to excluded all `.js` files in *node_modules* from `babel` for performance reasons.\n  2. However, it will also exclude `react-native-portal` from transpiling properly. To prevent that, we can use boolean condition to `exclude` option as noted.\n  3. if you are not using `stage-N` or proper `env` preset you may have to add `transform-class-properties` plugin.\n  4. if you are not using [`flow`](https://flow.org) you must add `transform-flow-strip-types` plugin.\n\n\u003c/details\u003e\n\n\n# Components\n\n## `PortalProvider` = context provider, required\n\n Match `BlackPortal` and `WhitePortal` by their name. Wrap your app with this component, presumably in App.js or index.js\n\n```html\n\u003cPortalProvider\u003e\n  \u003cYourAppRoot /\u003e\n\u003c/PortalProvider\u003e\n```\n\n## `BlackPortal` = Put things in here\n\nSends its child until `WhitePortal` renders, and always render `null` in its place. Once unmounted, it will wipe its `children` to `null`.\n\n### props\n\n- `name` : `string`\n- `children` : `ReactElement\u003c*\u003e | null`\n\n```html\n\u003cBlackPortal name=\"wow\"\u003e\n  \u003cMyButton onPress={this.whatever} title=\"I'm going to space\"/\u003e\n\u003c/BlackPortal\u003e\n\n\u003cBlackPortal name={`greet-${user.id}`}\u003e\n  \u003cSkeletal\u003eHello, {user.name}!\u003c/Skeletal\u003e\n\u003c/BlackPortal\u003e\n```\n\nIf there are no matching exit(`WhitePortal`), `PortalProvider` will simply hold it until requested.\n\n## `WhitePortal` = Things will pop out of here\n\nRenders anything sent from `BlackPortal`. Renders its given child as a fallback.\n\n### props\n\n- `name` : `string`\n- `children` : `?ReactElement\u003c*\u003e` - a default child. default: `null`\n- `childrenProps` : `?object` - inject props if provided\n\n```html\n\u003cWhitePortal name=\"wow\"\u003e\n  \u003cText\u003eI only render when there is nothing(falsy) to render from my name\u003c/Text\u003e\n\u003c/WhitePortal\u003e\n\n\u003cWhitePortal name={`greet-${user.id}`} childrenProps={{doot:'thank'}} /\u003e\n==\u003e renders \u003cSkeletal doot=\"thank\"\u003e…\u003c/Skeletal\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenyr%2Freact-native-portal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzenyr%2Freact-native-portal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenyr%2Freact-native-portal/lists"}