Render React DOM into a new context (aka "Portal")
This can be used to implement various UI components such as modals.
See react-modal2
.
It also works in universal (isomorphic) React applications without any additional setup and in React Native applications when used correctly.
$ npm install --save react-gateway
import React from 'react';
import {
Gateway,
GatewayDest,
GatewayProvider
} from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<div>
<h1>React Gateway Universal Example</h1>
<div className="container">
<Gateway into="one">
<div className="item">Item 1</div>
</Gateway>
<Gateway into="two">
<div className="item">Item 2</div>
</Gateway>
<div className="item">Item 3</div>
</div>
<GatewayDest name="one" component="section" className="hello"/>
<GatewayDest name="two"/>
</div>
</GatewayProvider>
);
}
}
Will render as:
<div>
<h1>React Gateway Universal Example</h1>
<div className="container">
<noscript></noscript>
<noscript></noscript>
<div className="item">Item 3</div>
</div>
<section className="hello">
<div className="item">Item 1</div>
</section>
<div>
<div className="item">Item 2</div>
</div>
</div>
To get started with React Gateway, first wrap your application in the
<GatewayProvider>
.
import React from 'react';
+ import {
+ GatewayProvider
+ } from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
+ <GatewayProvider>
<div>
{this.props.children}
</div>
+ </GatewayProvider>
);
}
}
Then insert a <GatewayDest>
whereever you want it to render and give it a
name.
import React from 'react';
import {
GatewayProvider,
+ GatewayDest
} from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<div>
{this.props.children}
+ <GatewayDest name="global"/>
</div>
</GatewayProvider>
);
}
}
Then in any of your components (that get rendered inside of the
<GatewayProvider>
) add a <Gateway>
.
import React from 'react';
+ import {Gateway} from 'react-gateway';
export default class MyComponent extends React.Component {
render() {
return (
<div>
+ <Gateway into="global">
+ Will render into the "global" gateway.
+ </Gateway>
</div>
);
}
}
If you want to customize the <GatewayDest>
element, you can pass any props,
including component
(which will allows you to specify a tagName
or custom
component), and they will be passed to the created element.
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<div>
{this.props.children}
- <GatewayDest name="global"/>
+ <GatewayDest name="global" component="section" className="global-gateway"/>
</div>
</GatewayProvider>
);
}
}
React Gateway works very differently than most React "portals" in order to work in server-side rendered React applications.
It maintains an internal registry of "containers" and "children" which manages where things should be rendered.
This registry is created by <GatewayProvider>
and passed to <Gateway>
and
<GatewayDest>
invisibly via React's contextTypes
.
Whenever a child or container is added or removed, React Gateway will update its internal registry and ensure things are properly rendered.
React Gateway does not directly depend on react-dom
, so it works fine with
React Native under one condition:
You must pass React Native component like View
or similar to
component
prop of <GatewayDest>
.
Because if you don't, <GatewayDest>
will try to render div
element, which
is not available.
import React from 'react';
import { Text, View } from 'react-native';
import {
Gateway,
GatewayDest,
GatewayProvider
} from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<View>
<Text>React Gateway Native Example</Text>
<View>
<Gateway into="one">
<Text>Text rendered elsewhere</Text>
</Gateway>
</View>
<GatewayDest name="one" component={View} />
</View>
</GatewayProvider>
);
}
}