ReactNativeを使って既存Webサービスのアプリ版を開発している場合、一部のアプリ独自の機能(例えばプッシュ通知やカメラ)を除いては既存ソースを流用できる場合があります。 例でいうと、ユーザ情報画面は既存のWebのマイページをそのまま表示するとかです。 その場合、WebViewを使うことになると思います。 ReactNativeでいうところのWebViewはreact-native-webviewを使うことになりますが、ここで問題になってくるのがReactNative側のコードとWebView側のコードの連携処理です。 先のマイページの例でいうと、WebView側のマイページ画面のソースコードにReactNative側からユーザ情報を渡してあげなければ成立しません。 今回はreact-native-webviewを導入した上で、WebViewとの値の受け渡し方法について調べました。
この記事はQiita -【ReactNative】WebViewを使って既存資産を使い回すのリライト記事です。
react-native
でプロジェクト作成済今回はreact-native-webview
を使用します。
yarn add react-native-webview
pod install
を行います。
cd ios && pod install
単純にWebページを表示するだけでなく、アプリとWebページ間での値の受渡しができます。 よって、ログイン画面をWebページ側で作って、ログイン後画面をアプリで実装なんてこともできます。
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
側から何らかのデータを受け取りたい場合は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
間でのデータの受け渡し方法を紹介しました。
既存のソースを使いまわせるので非常に有効な手ではないかと思います。