Reagieren Native WebView postMessage funktioniert nicht

Lesezeit: 6 Minuten

Benutzer-Avatar
Skarbo

Ich kann React Native WebView postMessage nicht zum Laufen bringen. Die React Native-App empfängt erfolgreich die Post-Nachricht sendt von der Web-App. Aber die Web-App empfängt keine Nachrichten, die von der React Native-App gesendet werden.

Meine einfache Web-App

<html>
<body>

<button>Send post message from web</button>
<div>Post message log</div>
<textarea style="height: 50%; width: 100%;" readonly></textarea>

<script>
var log = document.querySelector("textarea");

document.querySelector("button").onclick = function() {
    console.log("Send post message");

    logMessage("Sending post message from web..");
    window.postMessage("Post message from web", "*");
}

window.addEventListener("message", function(event) {
    console.log("Received post message", event);

    logMessage(event.data);
}, false);

function logMessage(message) {
    log.append((new Date()) + " " + message + "\n");
}

</script>

</body>
</html>

Diese Web-App wird gehostet unter: https://popping-heat-6062.firebaseapp.com/

Meine einfache React Native App

import React, {Component} from "react";
import {AppRegistry, Text, View, TouchableHighlight, WebView} from "react-native";

export default class WevViewApp extends Component {

    constructor( props ) {
        super( props );

        this.webView = null;
    }

    onMessage( event ) {
        console.log( "On Message", event.nativeEvent.data );
    }

    sendPostMessage() {
        console.log( "Sending post message" );
        this.webView.postMessage( "Post message from react native" );
    }

    render() {
        return (
            <View style={{flex: 1}}>
                <TouchableHighlight style={{padding: 10, backgroundColor: 'blue', marginTop: 20}} onPress={() => this.sendPostMessage()}>
                    <Text style={{color: 'white'}}>Send post message from react native</Text>
                </TouchableHighlight>
                <WebView
                    style={{flex: 1}}
                    source={{uri: 'https://popping-heat-6062.firebaseapp.com'}}
                    ref={( webView ) => this.webView = webView}
                    onMessage={this.onMessage}
                />
            </View>
        );
    }
}

AppRegistry.registerComponent( 'WevViewApp', () => WevViewApp );

Erwartetes Ergebnis

  1. Durch Klicken auf die Schaltfläche “Post-Nachricht aus dem Web senden” wird eine Post-Nachricht an die React Native-App gesendet und im Debugger-Fenster angemeldet
  2. Durch Klicken auf die Schaltfläche “Post-Nachricht von React Native senden” wird eine Post-Nachricht an die Web-App gesendet und im Web-Textbereich ausgedruckt

Tatsächliche Ergebnis

  1. Web-App erfolgreich sends sendet eine Nachricht an die React Native App und wird im Debugger-Fenster protokolliert
  2. Reagieren Sie auf die native App vergeblich sendet Nachricht an Web-App und wird nicht im Web-Textbereich ausgedruckt

Weiß jemand, warum die Web-App die Nachrichten nicht empfängt?

Getestet mit Android und iOS.

Dazugehörige Dokumentation: https://facebook.github.io/react-native/docs/webview.html


Bearbeiten: Es ist ein Verhalten aufgetreten, das das Problem lokalisieren kann.

Beim Testen der Schaltfläche „Post-Nachricht aus dem Web senden“ direkt in einem Webbrowser protokolliert das Textfeld, dass es die Nachricht gesendet hat und auch, dass es seine eigene Nachricht erhalten hat.

Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Sending post message from web..
Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Post message from web

Wenn Sie dasselbe in der WebView der React Native-App versuchen, wird der Textbereich nur ausgedruckt

Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Sending post message from web..

Entführt die WebView die Methode window.postMessage und fügt eine benutzerdefinierte Methode ein?

Dies wird in der erwähnt Dokumentation:

Wenn Sie diese Eigenschaft festlegen, wird eine globale postMessage in Ihre Webansicht eingefügt, es werden jedoch weiterhin bereits vorhandene Werte von postMessage aufgerufen.

Vielleicht ist das falsch und hier liegt das Problem?

  • Ich habe das gleiche Problem, habe den ganzen Tag damit verbracht, nach einer Problemumgehung zu suchen, aber es gibt keine, es ist eine Pull-Anfrage in Bearbeitung, vielleicht bekommen wir eine Lösung. github.com/facebook/react-native/pull/10941

    – Bhaumik Desai

    15. Dezember 2016 um 15:17 Uhr

Benutzer-Avatar
Ich frag mich

Ich hatte das gleiche Problem und habe es behoben, indem ich den Ereignis-Listener zum Dokument anstelle des Fensters hinzugefügt habe. Veränderung:

window.addEventListener("message", ...

zu:

document.addEventListener("message", ...

  • Das funktioniert. Vielen Dank. Denken Sie daran, wenn Sie auch normale Browser unterstützen möchten, sollten Sie beide definieren document.addEventListener("message", ... und window.addEventListener("message", ....

    – Skarbo

    29. Januar 2017 um 20:51 Uhr

  • Danke, das war sehr hilfreich und hat mir einige Zeit gespart, viel Spaß mit dem Kopfgeld.

    – Äther

    8. Februar 2017 um 14:46 Uhr

  • Kann das jemand erklären?

    – Yuriy Chachora

    17. August 2017 um 11:26 Uhr

  • @YuriyChachora weil es so implementiert ist: github.com/facebook/react-native/blob/master/ReactAndroid/src/…

    – Dan Feld

    8. November 2017 um 2:11 Uhr

  • Und für iOS: github.com/facebook/react-native/blob/master/React/Views/…

    – Dan Feld

    8. November 2017 um 2:15 Uhr

Version 5 von React-Native-Webview ändert, wie dieses Verhalten funktioniert. Sie wollen jetzt:

window.ReactNativeWebView.postMessage(data);

  • Es funktionierte. Schlaue Antwort 🙂

    – deva11

    21. April 2020 um 9:42 Uhr

  • Gute Antwort. Für mich gelöst!

    – Parth Chokshi

    29. Juni 2020 um 6:00 Uhr

  • Für mich gelöst!

    – b.stevens.photo

    10. September 2020 um 18:19 Uhr

  • Hat bei mir funktioniert, vielen Dank

    – Prof. Mushiana Mulweli

    28. August 2021 um 9:51 Uhr

Benutzer-Avatar
Keshav Gera

Fügen Sie browserspezifische Ereignis-Listener hinzu

Bei Android

 document.addEventListener("message", function(event) {
       alert("This is a Entry Point Working in Android");
       init(event.data)
  });

Unter iOS

 window.addEventListener("message", function(event) {
       alert("This is a Entry Point Working in iOS");
       init(event.data)
  });

Geben Sie hier die Bildbeschreibung ein

Benutzer-Avatar
Nirojan

Tatsächlich funktioniert der Listener in verschiedenen Betriebssystemen wie iOS und Android unterschiedlich. Sie sollten also verwenden document.addEventListener für Android u window.addEventListener für iOS.

if (navigator.appVersion.includes('Android')) {
  document.addEventListener("message", function (data) {
    alert("you are in android OS");
  });
}
else {
  window.addEventListener("message", function (data) {
    alert("you are in android OS");
  });
}

Keine der obigen Antworten funktioniert für IOS, funktioniert möglicherweise immer noch für Android-Geräte. Dieser Weg funktioniert für alle Plattformen –

In Reaktion nativ:

const generateOnMessageFunction = data =>
    `(function() {
    window.WebViewBridge.onMessage(${JSON.stringify(data)});
  })()`;

class RNScreen extends React.Component{
      private webView: RefObject<WebView> = createRef();
       render(){
              return (
                    <WebView
                            javaScriptEnabled
                            domStorageEnabled
                            bounces={false}
                            ref={this.webView}
                            onLoadEnd={() => {
                                this.postMessageTest({helloFromRN: true});
                            }}
                      />
              )
       }

      private postMessageTest(data){
             this.webView.current.injectJavaScript(generateOnMessageFunction(data));
      }

}

IN JS-Seite –

window.WebViewBridge = {
    onMessage: this._onMessage,
};
const event = new Event('WebViewBridge');
window.dispatchEvent(event);


// The data is not a string. It is an object.
private _onMessage(data: Object){
    // Should log "helloFromRN" on load.
    console.log(data)
}

Sie können die folgenden Schritte für Pub/Sub ausführen =>>

Schritt 1 => Plugin in Ihrer React-Native-App hinzufügen:
https://github.com/react-native-webview/react-native-webview

Schritt 2 => Fügen Sie den folgenden Code in ReactNative (Mobile Part) hinzu:

import React, { Component } from "react";
import { SafeAreaView, Text, TouchableHighlight } from "react-native";
import { WebView } from "react-native-webview";

class MobileWebView extends Component {
  state = {};

  onMessage = event => {
    const { data } = event.nativeEvent;
    this.setState({ data });
  };

  render() {
    return (
      <SafeAreaView style={{ flex: 1 }}>
        <TouchableHighlight
          style={{
            padding: 10,
            backgroundColor: "red",
            width: "100%",
          }}
          onPress={() => {
            this.webview.postMessage("Message From React Native App to Web");
          }}
        >
          <Text>Send Message To Web</Text>
        </TouchableHighlight>
        <Text>Mobile: {this.state.data}</Text>
        <WebView
          ref={ref => {
            this.webview = ref;
          }}
          source={{ uri: "http://localhost:3000/" }}
          onMessage={this.onMessage}
          style={{ flex: 1 }}
        />
      </SafeAreaView>
    );
  }
}

export default MobileWebView;

Schritt 3 => Fügen Sie den folgenden Code in ReactJS (Web Part) hinzu:

import React, { Component } from "react";

class WebApp extends Component {
  state = {};
  componentDidMount() {
    document.addEventListener("message", event => {
      this.setState({ msg: event.data });
    });
    window.addEventListener("message", event => {
      this.setState({ msg: event.data });
    });
  }

  render() {
    return (
      <div>
        <div>Web: {this.state.msg}</div>

        <button
          onClick={() => {
            window.ReactNativeWebView.postMessage(
              "Post message from web to Mobile",
              "*"
            );
          }}
        >
          Send Message To React Native(Mobile)
        </button>
      </div>
    );
  }
}

export default WebApp;

Und Sie können loslegen, jetzt können Sie Nachrichten vom Handy zum Web senden und empfangen oder umgekehrt.

Ausgabebild

1245940cookie-checkReagieren Native WebView postMessage funktioniert nicht

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy