react-native-portal
v1.3.0
Published
Translocate your render destination, using mitt. Built with react@16 and react-native in mind.
Downloads
8,768
Maintainers
Readme
react-native-portal
Translocate your render destination. Using mitt
. Built with react@16
and react-native
in mind, but these are not strictly required, as long as React.PureComponent
is available.
The code itself is very minimal and only rely on react's context
, and written in ES6
.
Feel free to file an issue/PR if you have a better way to publish this component.
Live demo on web
- Although I built this module for
react-native
, it works just as great on web. - https://codepen.io/zenyr/pen/xLrKPZ
Aim of this project
- Minimalistic API
- Minimal dependancy
- Use official react API only
Known issues
- Try not to put falsy
0
or''
through. ( ͡° ͜ʖ ͡°) - A behavior of
BlackPortal
s having the exact samename
is undefined, yet.- Ideas appreciated
- Uncanny resemblance with cloudflare/react-gateway
- This one is smaller though
- Has
react-native
in its name but works on anywhere including browser DOM. - (webpack only) needs proper babel configuration (see ES6 usage and ES5 usage below)
Install
- install npm module
npm i react-native-portal -P
or
yarn add react-native-portal --prod
Make sure to put -P
or --prod
to ignore useless packages for consuming this module.
It should automatically install mitt
, only if necessary.
- Wrap your root component with
PortalProvider
.
As it requires a single child it is reasonable to wrap it in your entry file.
import {PortalProvider} from 'react-native-portal'
...
render(<PortalProvider><YourApp /></PortalProvider>, document.querySelector('#app'))
- Put your WhitePortal and BlackPortal as you wish, matching their
name
props. - Enjoy your inner peace 🙏
ES5 usage
You can access this module on react-dom
+ legacy browser environment via unpkg.
Good enough for quick prototyping and goofying around.
https://unpkg.com/react-native-portal/dist/es5.js
https://unpkg.com/react-native-portal/dist/min.js
(expects React global, prop-types & mitt bundled)
However I do not recommend this on production 😂
ES6 usage (outside of react-native
)
Only refer this if you are going to use this module on browsers or a modified environment.
Since 1.1.1 I've included dist/noflow.js
in the npm repo.
It sticks to the pure es6 spec (as of es2015) so you won't need to strip away class properties and flow comments.
import {PortalProvider} from 'react-native-portal/dist/noflow';
(I'd better improve those filenames. I'll do a major semver update in that case!)
module: {
rules: [
...
{
test: /\.js$/,
exclude: {
and: [
/(node_modules|bower_components)/, // << Note 1
{ not: [/(react-native-portal)/] }, // << Note 2
],
},
use: {
loader: 'babel-loader',
options: {
presets: [
...
],
plugins: [
...,
['transform-class-properties', { spec: false }], // <<< Note 3. `spec` is optional
['transform-flow-strip-types'], // <<< Note 4. Only if you are NOT using flow
],
},
},
},
},
...
}
Above snippet from webpack.config.js
has 3 lines that you may have to set up properly with babel-loader
.
- It is advised to excluded all
.js
files in node_modules frombabel
for performance reasons. - However, it will also exclude
react-native-portal
from transpiling properly. To prevent that, we can use boolean condition toexclude
option as noted. - if you are not using
stage-N
or properenv
preset you may have to addtransform-class-properties
plugin. - if you are not using
flow
you must addtransform-flow-strip-types
plugin.
Components
PortalProvider
= context provider, required
Match BlackPortal
and WhitePortal
by their name. Wrap your app with this component, presumably in App.js or index.js
<PortalProvider>
<YourAppRoot />
</PortalProvider>
BlackPortal
= Put things in here
Sends its child until WhitePortal
renders, and always render null
in its place. Once unmounted, it will wipe its children
to null
.
props
name
:string
children
:ReactElement<*> | null
<BlackPortal name="wow">
<MyButton onPress={this.whatever} title="I'm going to space"/>
</BlackPortal>
<BlackPortal name={`greet-${user.id}`}>
<Skeletal>Hello, {user.name}!</Skeletal>
</BlackPortal>
If there are no matching exit(WhitePortal
), PortalProvider
will simply hold it until requested.
WhitePortal
= Things will pop out of here
Renders anything sent from BlackPortal
. Renders its given child as a fallback.
props
name
:string
children
:?ReactElement<*>
- a default child. default:null
childrenProps
:?object
- inject props if provided
<WhitePortal name="wow">
<Text>I only render when there is nothing(falsy) to render from my name</Text>
</WhitePortal>
<WhitePortal name={`greet-${user.id}`} childrenProps={{doot:'thank'}} />
==> renders <Skeletal doot="thank">…</Skeletal>