はじめに
ReactNative
を使って既存Webサービスのアプリ版を開発している場合、一部のアプリ独自の機能(例えばプッシュ通知やカメラ)を除いては既存ソースを流用できる場合があります。
例でいうと、ユーザ情報画面は既存のWebのマイページをそのまま表示するとかです。
その場合、WebView
を使うことになると思います。
ReactNative
でいうところのWebView
はreact-native-webview
を使うことになりますが、ここで問題になってくるのがReactNative
側のコードとWebView
側のコードの連携処理です。
先のマイページの例でいうと、WebView
側のマイページ画面のソースコードにReactNative
側からユーザ情報を渡してあげなければ成立しません。
今回はreact-native-webview
を導入した上で、WebView
との値の受け渡し方法について調べました。
環境情報
"react-native": "0.61.5",
"react-native-webview": "^9.2.1",
インストール
react-native-webview
をインストールしていない場合はインストール。
yarn add react-native-webview
WebViewに値を渡す
WebView
に値を渡す場合はinjectedJavaScript
を使います。
injectedJavaScript
には文字列型でJavascript
のコードを渡せます。
import React from 'react';
import { WebView } from 'react-native-webview';
// WebViewに渡すコード
const injectedCode : string = `
function fireInjectedJavaScript(){
alert('ReactNativeから渡されたコードを実行しました!');
}
`;
// WebViewで表示させるHTML
const html : string = `
<html>
<head>
</head>
<body>
<h1>Title</h1>
<form name="test">
<input type="button" value="injectedJavaScript" onClick="fireInjectedJavaScript()">
</form>
</body>
</html>
`;
// ...割愛
render(
<WebView source={{html : html}} injectedJavaScript={injectedCode} />
);
html
中のボタンでfireInjectedJavascript()
を実行していますが、これはReactNative
側から渡された関数です。
よって、アプリで表示された場合のみ特定の処理を行うような作りにすることもできます。
渡したコードはWebView
が描画された後に実行されるため、jQuery
やdocument.getElementById
なんかを使ってWebView
側の特定のフォームの値や表示をいじることもできます(上記のマイページの例ではこの方法を使ってユーザ情報を渡す)。
WebViewから値を貰う
逆にWebView
側から何らかのデータを受け取りたい場合はonMessage
を使います。
import React from 'react';
import { WebView, WebViewMessageEvent } from 'react-native-webview';
// WebViewで表示させるHTML
const html : string = `
<html>
<head>
<script>
// WebViewが読み込まれた時にデータを送信
window.onload = function() {
window.ReactNativeWebView.postMessage("onload")
};
// 定期的に実行(ポーリングなんかに使える??)
setInterval(function () {
window.ReactNativeWebView.postMessage({hoge : "setInterval"})
}, 2000)
// 特定の処理実行時にデータを送信
function firePostMessage(){
window.ReactNativeWebView.postMessage("button click")
}
</script>
</head>
<body>
<h1>Title</h1>
<form name="test">
<input type="button" value="postMessage" onClick="firePostMessage()">
</form>
</body>
</html>
`;
// ...割愛
// onMessage発火時処理
public onMessageFromHtml(event : WebViewMessageEvent) {
console.log(event.nativeEvent.data);
}
render(
<WebView source={{html : html}} onMessage={onMessageFromHtml} />
);
上記の例ではWebView
読み込み時に実行と、定期的に実行、ボタンを押した時に実行、と3パターンを盛り込んでいます。
いずれの場合もwindow.ReactNativeWebView.postMessage
を実行しており、ReactNative
側ではWebViewMessageEvent
型で受け取ります。
渡された値自体はWebViewMessageEvent
のnativeEvent.data
の中に格納されています。
nativeEvent.data
はreact
のBaseSyntheticEvent
のジェネリクスとなっているため型は自由です(setIntervalのようにオブジェクトを渡すこともできます)。
おわりに
今回はreact-natiev-webview
をインストールし、ReactNative
とWebView
間でのデータの受け渡し方法を紹介しました。
既存のソースを使いまわせるので非常に有効な手ではないかと思います。