62
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[React Native]ReactNativeとWebViewのデータ連携

Last updated at Posted at 2018-02-02

概要

  • ReactNativeのアプリでWebViewを使う時に、Reactの世界とWebViewの世界でデータのやり取りをする方法を調べたのでそれの紹介

本題

WebViewとは

  • スマホアプリの中にWebページを表示する仕組み

ReactNativeのWebView

  • ReactNativeではWebViewというコンポーネントが用意されている
  • WebViewコンポーネントにURLを属性で渡すとアプリでWebページを表示できるようになる
  • ViewとかTextとかのコンポーネントと同じ感覚で配置するだけで使える

何をやりたいのか

  • アプリの中にWebViewを埋め込む時に相互にデータのやりとりをしたい
    • WebView内で入力した情報をアプリ側で使用したいとか
    • アプリ側で持っている情報をWebView内に埋め込みたいとか

アプリ->WebView

  • アプリからWebViewに情報を渡す方法

やり方

  • アプリからWebViewへJavaScriptのコードを渡して実行できる
  • 以下の2パターンがある
WebView作成時に渡すパターン
const jsCode = `
const inputName = document.getElementById('input-name');
inputName.value = 'ozaki';
`
class xxx extends Components {
  render() {
    return(
      <WebView
        source={'http://localhost:8080/'}
        injectedJavaScript={jsCode}
      />
    )
  }
}
  • 渡したコードはWebView生成後に画面内に埋め込まれる
    • 上記の例では画面の描画直後に実行されて、入力域にozakiと入った状態で画面が表示される
  • JavaScriptのコードはStringで渡さなければいけないのでちょっと扱いづらい
WebView作成後に実行するパターン
const jsCode = `
const inputName = document.getElementById('input-name');
inputName.value = 'ozaki';
`
class xxx extends Component {
  someFunc() {
    this.webview.injectjavascript(jsCode)
  }
  render() {
    return(
      <WebView
        ref={ref => this.webview = ref}
        source={'http://localhost:8080/'}
      />
    )
  }
}
  • このパターンではinjectjavascriptの引数に渡したJavaScriptが実行される
    • 上記の例では、someFuncを呼ぶと、入力域にozakiと値が入ることになる
  • こちらもJavaScriptのコードはStringで渡さないといけない

WebView->アプリ

  • WebViewからアプリに情報を渡す方法

postMessageとonMessage

  • Webページにはwindowに対してpostMessageという関数が紐付けられている
  • このpostMessageを実行するとWebViewからアプリにデータの送信ができる
  • アプリ側はonMessageメソッドを定義することでpostMessageの送信内容を受信することができる
// ReactNative側
class xxx extends Component {
  onMessage = (event) => {
    const { data } = event.nativeEvent;
    if (data === 'OK') {
      alert('OK!');
    } else if (data === 'NG') {
      alert('NG');
    }
  };
}

// WebView側
window.postMessage('OK');
  • postMessageの引数はevent.nativeEvent.dataで取得できる
  • postMessageの引数はStringしか渡すことができない

まとめ

  • アプリとWebViewのデータ連携はあまり柔軟性がない
    • セキュリティ的な要因とかなのかな?
  • とはいえ、最低限の連携はできるので大抵のケースはこれだけできれば十分だと思う

追記

  • バージョンが上がっていつの間にかドキュメントにSecurityWarningが追加されていました

Security Warning: Currently, onMessage and postMessage do not allow specifying an origin. This can lead to cross-site scripting attacks if an unexpected document is loaded within a WebView instance. Please refer to the MDN documentation for Window.postMessage() for more details on the security implications of this.

62
60
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?