1 | # React Gateway
|
2 |
|
3 | > Render React DOM into a new context (aka "Portal")
|
4 |
|
5 | This can be used to implement various UI components such as modals.
|
6 | See [`react-modal2`](https://github.com/cloudflare/react-modal2).
|
7 |
|
8 | It also works in universal (isomorphic) React applications without any
|
9 | additional setup and in React Native applications
|
10 | [when used correctly](#react-native-example).
|
11 |
|
12 | ## Installation
|
13 |
|
14 | ```sh
|
15 | $ npm install --save react-gateway
|
16 | ```
|
17 |
|
18 | ## Example
|
19 |
|
20 | ```js
|
21 | import React from 'react';
|
22 | import {
|
23 | Gateway,
|
24 | GatewayDest,
|
25 | GatewayProvider
|
26 | } from 'react-gateway';
|
27 |
|
28 | export default class Application extends React.Component {
|
29 | render() {
|
30 | return (
|
31 | <GatewayProvider>
|
32 | <div>
|
33 | <h1>React Gateway Universal Example</h1>
|
34 | <div className="container">
|
35 | <Gateway into="one">
|
36 | <div className="item">Item 1</div>
|
37 | </Gateway>
|
38 | <Gateway into="two">
|
39 | <div className="item">Item 2</div>
|
40 | </Gateway>
|
41 | <div className="item">Item 3</div>
|
42 | </div>
|
43 | <GatewayDest name="one" component="section" className="hello"/>
|
44 | <GatewayDest name="two"/>
|
45 | </div>
|
46 | </GatewayProvider>
|
47 | );
|
48 | }
|
49 | }
|
50 | ```
|
51 |
|
52 | Will render as:
|
53 |
|
54 | ```js
|
55 | <div>
|
56 | <h1>React Gateway Universal Example</h1>
|
57 | <div className="container">
|
58 | <noscript></noscript>
|
59 | <noscript></noscript>
|
60 | <div className="item">Item 3</div>
|
61 | </div>
|
62 | <section className="hello">
|
63 | <div className="item">Item 1</div>
|
64 | </section>
|
65 | <div>
|
66 | <div className="item">Item 2</div>
|
67 | </div>
|
68 | </div>
|
69 | ```
|
70 |
|
71 | ## Usage
|
72 |
|
73 | To get started with React Gateway, first wrap your application in the
|
74 | `<GatewayProvider>`.
|
75 |
|
76 | ```diff
|
77 | import React from 'react';
|
78 | + import {
|
79 | + GatewayProvider
|
80 | + } from 'react-gateway';
|
81 |
|
82 | export default class Application extends React.Component {
|
83 | render() {
|
84 | return (
|
85 | + <GatewayProvider>
|
86 | <div>
|
87 | {this.props.children}
|
88 | </div>
|
89 | + </GatewayProvider>
|
90 | );
|
91 | }
|
92 | }
|
93 | ```
|
94 |
|
95 | Then insert a `<GatewayDest>` whereever you want it to render and give it a
|
96 | name.
|
97 |
|
98 | ```diff
|
99 | import React from 'react';
|
100 | import {
|
101 | GatewayProvider,
|
102 | + GatewayDest
|
103 | } from 'react-gateway';
|
104 |
|
105 | export default class Application extends React.Component {
|
106 | render() {
|
107 | return (
|
108 | <GatewayProvider>
|
109 | <div>
|
110 | {this.props.children}
|
111 | + <GatewayDest name="global"/>
|
112 | </div>
|
113 | </GatewayProvider>
|
114 | );
|
115 | }
|
116 | }
|
117 | ```
|
118 |
|
119 | Then in any of your components (that get rendered inside of the
|
120 | `<GatewayProvider>`) add a `<Gateway>`.
|
121 |
|
122 | ```diff
|
123 | import React from 'react';
|
124 | + import {Gateway} from 'react-gateway';
|
125 |
|
126 | export default class MyComponent extends React.Component {
|
127 | render() {
|
128 | return (
|
129 | <div>
|
130 | + <Gateway into="global">
|
131 | + Will render into the "global" gateway.
|
132 | + </Gateway>
|
133 | </div>
|
134 | );
|
135 | }
|
136 | }
|
137 | ```
|
138 |
|
139 | If you want to customize the `<GatewayDest>` element, you can pass any props,
|
140 | including `component` (which will allows you to specify a `tagName` or custom
|
141 | component), and they will be passed to the created element.
|
142 |
|
143 | ```diff
|
144 | export default class Application extends React.Component {
|
145 | render() {
|
146 | return (
|
147 | <GatewayProvider>
|
148 | <div>
|
149 | {this.props.children}
|
150 | - <GatewayDest name="global"/>
|
151 | + <GatewayDest name="global" component="section" className="global-gateway"/>
|
152 | </div>
|
153 | </GatewayProvider>
|
154 | );
|
155 | }
|
156 | }
|
157 | ```
|
158 |
|
159 | ## How it works
|
160 |
|
161 | React Gateway works very differently than most React "portals" in order to work
|
162 | in server-side rendered React applications.
|
163 |
|
164 | It maintains an internal registry of "containers" and "children" which manages
|
165 | where things should be rendered.
|
166 |
|
167 | This registry is created by `<GatewayProvider>` and passed to `<Gateway>` and
|
168 | `<GatewayDest>` invisibly via React's `contextTypes`.
|
169 |
|
170 | Whenever a child or container is added or removed, React Gateway will
|
171 | update its internal registry and ensure things are properly rendered.
|
172 |
|
173 | ## React Native example
|
174 |
|
175 | React Gateway does not directly depend on `react-dom`, so it works fine with
|
176 | React Native under one condition:
|
177 |
|
178 | **You must pass React Native component like `View` or similar to
|
179 | `component` prop of `<GatewayDest>`.**
|
180 |
|
181 | Because if you don't, `<GatewayDest>` will try to render `div` element, which
|
182 | is not available.
|
183 |
|
184 | ```js
|
185 | import React from 'react';
|
186 | import { Text, View } from 'react-native';
|
187 | import {
|
188 | Gateway,
|
189 | GatewayDest,
|
190 | GatewayProvider
|
191 | } from 'react-gateway';
|
192 |
|
193 | export default class Application extends React.Component {
|
194 | render() {
|
195 | return (
|
196 | <GatewayProvider>
|
197 | <View>
|
198 | <Text>React Gateway Native Example</Text>
|
199 | <View>
|
200 | <Gateway into="one">
|
201 | <Text>Text rendered elsewhere</Text>
|
202 | </Gateway>
|
203 | </View>
|
204 | <GatewayDest name="one" component={View} />
|
205 | </View>
|
206 | </GatewayProvider>
|
207 | );
|
208 | }
|
209 | }
|
210 | ```
|