|
@@ -14,7 +14,6 @@ _This guide is currently a work in progress._
|
14
|
14
|
- [Add support for File Download](Guide.md#add-support-for-file-download)
|
15
|
15
|
- [Communicating between JS and Native](Guide.md#communicating-between-js-and-native)
|
16
|
16
|
|
17
|
|
-
|
18
|
17
|
### Basic inline HTML
|
19
|
18
|
|
20
|
19
|
The simplest way to use the WebView is to simply pipe in the HTML you want to display. Note that setting an `html` source requires the [originWhiteList](Reference.md#originWhiteList) property to be set to `['*']`.
|
|
@@ -48,9 +47,7 @@ import { WebView } from 'react-native-webview';
|
48
|
47
|
class MyWeb extends Component {
|
49
|
48
|
render() {
|
50
|
49
|
return (
|
51
|
|
- <WebView
|
52
|
|
- source={{uri: 'https://facebook.github.io/react-native/'}}
|
53
|
|
- />
|
|
50
|
+ <WebView source={{ uri: 'https://facebook.github.io/react-native/' }} />
|
54
|
51
|
);
|
55
|
52
|
}
|
56
|
53
|
}
|
|
@@ -71,7 +68,7 @@ class MyWeb extends Component {
|
71
|
68
|
return (
|
72
|
69
|
<WebView
|
73
|
70
|
ref={ref => (this.webview = ref)}
|
74
|
|
- source={{uri: 'https://facebook.github.io/react-native/'}}
|
|
71
|
+ source={{ uri: 'https://facebook.github.io/react-native/' }}
|
75
|
72
|
onNavigationStateChange={this.handleWebViewNavigationStateChange}
|
76
|
73
|
/>
|
77
|
74
|
);
|
|
@@ -87,7 +84,7 @@ class MyWeb extends Component {
|
87
|
84
|
// canGoForward?: boolean;
|
88
|
85
|
// }
|
89
|
86
|
const { url } = newNavState;
|
90
|
|
- if (!url) return
|
|
87
|
+ if (!url) return;
|
91
|
88
|
|
92
|
89
|
// handle certain doctypes
|
93
|
90
|
if (url.includes('.pdf')) {
|
|
@@ -112,10 +109,48 @@ class MyWeb extends Component {
|
112
|
109
|
const redirectTo = 'window.location = "' + newURL + '"';
|
113
|
110
|
this.webview.injectJavaScript(redirectTo);
|
114
|
111
|
}
|
115
|
|
- }
|
|
112
|
+ };
|
116
|
113
|
}
|
117
|
114
|
```
|
118
|
115
|
|
|
116
|
+#### Intercepting hash URL changes
|
|
117
|
+
|
|
118
|
+While `onNavigationStateChange` will trigger on URL changes, it does not trigger when only the hash URL ("anchor") changes, e.g. from `https://example.com/users#list` to `https://example.com/users#help`.
|
|
119
|
+
|
|
120
|
+You can inject some JavaScript to wrap the history functions in order to intercept these hash URL changes.
|
|
121
|
+
|
|
122
|
+```jsx
|
|
123
|
+<WebView
|
|
124
|
+ source={{ uri: someURI }}
|
|
125
|
+ injectedJavaScript={`
|
|
126
|
+ (function() {
|
|
127
|
+ function wrap(fn) {
|
|
128
|
+ return function wrapper() {
|
|
129
|
+ var res = fn.apply(this, arguments);
|
|
130
|
+ window.ReactNativeWebView.postMessage('navigationStateChange');
|
|
131
|
+ return res;
|
|
132
|
+ }
|
|
133
|
+ }
|
|
134
|
+
|
|
135
|
+ history.pushState = wrap(history.pushState);
|
|
136
|
+ history.replaceState = wrap(history.replaceState);
|
|
137
|
+ window.addEventListener('popstate', function() {
|
|
138
|
+ window.ReactNativeWebView.postMessage('navigationStateChange');
|
|
139
|
+ });
|
|
140
|
+ })();
|
|
141
|
+
|
|
142
|
+ true;
|
|
143
|
+ `}
|
|
144
|
+ onMessage={({ nativeEvent: state }) => {
|
|
145
|
+ if (state.data === 'navigationStateChange') {
|
|
146
|
+ // Navigation state updated, can check state.canGoBack, etc.
|
|
147
|
+ }
|
|
148
|
+ }}
|
|
149
|
+/>
|
|
150
|
+```
|
|
151
|
+
|
|
152
|
+Thanks to [Janic Duplessis](https://github.com/react-native-community/react-native-webview/issues/24#issuecomment-483956651) for this workaround.
|
|
153
|
+
|
119
|
154
|
### Add support for File Upload
|
120
|
155
|
|
121
|
156
|
##### iOS
|
|
@@ -123,18 +158,21 @@ class MyWeb extends Component {
|
123
|
158
|
For iOS, all you need to do is specify the permissions in your `ios/[project]/Info.plist` file:
|
124
|
159
|
|
125
|
160
|
Photo capture:
|
|
161
|
+
|
126
|
162
|
```
|
127
|
163
|
<key>NSCameraUsageDescription</key>
|
128
|
164
|
<string>Take pictures for certain activities</string>
|
129
|
165
|
```
|
130
|
166
|
|
131
|
167
|
Gallery selection:
|
|
168
|
+
|
132
|
169
|
```
|
133
|
170
|
<key>NSPhotoLibraryUsageDescription</key>
|
134
|
171
|
<string>Select pictures for certain activities</string>
|
135
|
172
|
```
|
136
|
173
|
|
137
|
174
|
Video recording:
|
|
175
|
+
|
138
|
176
|
```
|
139
|
177
|
<key>NSMicrophoneUsageDescription</key>
|
140
|
178
|
<string>Need microphone access for recording videos</string>
|
|
@@ -143,6 +181,7 @@ Video recording:
|
143
|
181
|
##### Android
|
144
|
182
|
|
145
|
183
|
Add permission in AndroidManifest.xml:
|
|
184
|
+
|
146
|
185
|
```xml
|
147
|
186
|
<manifest ...>
|
148
|
187
|
......
|
|
@@ -173,7 +212,7 @@ WebView.isFileUploadSupported().then(res => {
|
173
|
212
|
|
174
|
213
|
### Multiple Files Upload
|
175
|
214
|
|
176
|
|
-You can control __single__ or __multiple__ file selection by specifing the [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#multiple) attribute on your `input` element:
|
|
215
|
+You can control **single** or **multiple** file selection by specifing the [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#multiple) attribute on your `input` element:
|
177
|
216
|
|
178
|
217
|
```
|
179
|
218
|
// multiple file selection
|
|
@@ -190,6 +229,7 @@ You can control __single__ or __multiple__ file selection by specifing the [`mul
|
190
|
229
|
For iOS, all you need to do is specify the permissions in your `ios/[project]/Info.plist` file:
|
191
|
230
|
|
192
|
231
|
Save to gallery:
|
|
232
|
+
|
193
|
233
|
```
|
194
|
234
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
195
|
235
|
<string>Save pictures for certain activities.</string>
|
|
@@ -225,9 +265,9 @@ To accomplish this, React Native WebView exposes three different options:
|
225
|
265
|
This is a script that runs immediately after the web page loads for the first time. It only runs once, even if the page is reloaded or navigated away.
|
226
|
266
|
|
227
|
267
|
```jsx
|
228
|
|
-import React, { Component } from "react";
|
229
|
|
-import { View } from "react-native";
|
230
|
|
-import { WebView } from "react-native-webview";
|
|
268
|
+import React, { Component } from 'react';
|
|
269
|
+import { View } from 'react-native';
|
|
270
|
+import { WebView } from 'react-native-webview';
|
231
|
271
|
|
232
|
272
|
export default class App extends Component {
|
233
|
273
|
render() {
|
|
@@ -241,7 +281,7 @@ export default class App extends Component {
|
241
|
281
|
<WebView
|
242
|
282
|
source={{
|
243
|
283
|
uri:
|
244
|
|
- "https://github.com/react-native-community/react-native-webview"
|
|
284
|
+ 'https://github.com/react-native-community/react-native-webview',
|
245
|
285
|
}}
|
246
|
286
|
injectedJavaScript={runFirst}
|
247
|
287
|
/>
|
|
@@ -255,7 +295,7 @@ This runs the JavaScript in the `runFirst` string once the page is loaded. In th
|
255
|
295
|
|
256
|
296
|
<img alt="screenshot of Github repo" width="200" src="https://user-images.githubusercontent.com/1479215/53609254-e5dc9c00-3b7a-11e9-9118-bc4e520ce6ca.png" />
|
257
|
297
|
|
258
|
|
-*Under the hood*
|
|
298
|
+_Under the hood_
|
259
|
299
|
|
260
|
300
|
> On iOS, `injectedJavaScript` runs a method on WKWebView called `evaluateJavaScript:completionHandler:`
|
261
|
301
|
> On Android, `injectedJavaScript` runs a method on the Android WebView called `evaluateJavascriptWithFallback`
|
|
@@ -265,9 +305,9 @@ This runs the JavaScript in the `runFirst` string once the page is loaded. In th
|
265
|
305
|
While convenient, the downside to the previously mentioned `injectedJavaScript` prop is that it only runs once. That's why we also expose a method on the webview ref called `injectJavaScript` (note the slightly different name!).
|
266
|
306
|
|
267
|
307
|
```jsx
|
268
|
|
-import React, { Component } from "react";
|
269
|
|
-import { View } from "react-native";
|
270
|
|
-import { WebView } from "react-native-webview";
|
|
308
|
+import React, { Component } from 'react';
|
|
309
|
+import { View } from 'react-native';
|
|
310
|
+import { WebView } from 'react-native-webview';
|
271
|
311
|
|
272
|
312
|
export default class App extends Component {
|
273
|
313
|
render() {
|
|
@@ -286,7 +326,7 @@ export default class App extends Component {
|
286
|
326
|
ref={r => (this.webref = r)}
|
287
|
327
|
source={{
|
288
|
328
|
uri:
|
289
|
|
- "https://github.com/react-native-community/react-native-webview"
|
|
329
|
+ 'https://github.com/react-native-community/react-native-webview',
|
290
|
330
|
}}
|
291
|
331
|
/>
|
292
|
332
|
</View>
|
|
@@ -299,7 +339,7 @@ After 3 seconds, this code turns the background blue:
|
299
|
339
|
|
300
|
340
|
<img alt="Screenshot of app showing injected javascript" width="200" src="https://user-images.githubusercontent.com/1479215/53670433-93a98280-3c2f-11e9-85a5-0e4650993817.png" />
|
301
|
341
|
|
302
|
|
-*Under the hood*
|
|
342
|
+_Under the hood_
|
303
|
343
|
|
304
|
344
|
> On iOS, `injectJavaScript` calls WKWebView's `evaluateJS:andThen:`
|
305
|
345
|
> On Android, `injectJavaScript` calls Android WebView's `evaluateJavascriptWithFallback` method
|
|
@@ -313,9 +353,9 @@ You _must_ set `onMessage` or the `window.ReactNativeWebView.postMessage` method
|
313
|
353
|
`window.ReactNativeWebView.postMessage` only accepts one argument which must be a string.
|
314
|
354
|
|
315
|
355
|
```jsx
|
316
|
|
-import React, { Component } from "react";
|
317
|
|
-import { View } from "react-native";
|
318
|
|
-import { WebView } from "react-native-webview";
|
|
356
|
+import React, { Component } from 'react';
|
|
357
|
+import { View } from 'react-native';
|
|
358
|
+import { WebView } from 'react-native-webview';
|
319
|
359
|
|
320
|
360
|
export default class App extends Component {
|
321
|
361
|
render() {
|
|
@@ -349,4 +389,3 @@ export default class App extends Component {
|
349
|
389
|
This code will result in this alert:
|
350
|
390
|
|
351
|
391
|
<img alt="Alert showing communication from web page to React Native" width="200" src="https://user-images.githubusercontent.com/1479215/53671269-7e822300-3c32-11e9-9937-7ddc34ba8af3.png" />
|
352
|
|
-
|