javascript React Native WebView postMessage不工作

x9ybnkn6  于 2023-03-21  发布在  Java
关注(0)|答案(7)|浏览(166)

我无法让React Native WebView postMessage工作。React Native应用成功接收到来自Web应用的post消息sendt。但Web应用没有接收到来自React Native应用的消息sendt。

我的简单网页应用

<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>

此Web应用程序托管在:https://popping-heat-6062.firebaseapp.com/

我的简单React Native应用

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 );

预期成果

1.点击“Send post message from web”按钮,向React Native应用程序发送一条post消息,并记录在调试器窗口中
1.点击“Send post message from React Native”按钮,会向Web应用程序发送一条post消息,并在Web文本区域中打印出来

实际结果

  1. Web应用成功向React Native应用发送消息,并记录在调试器窗口中
  2. React Native应用未成功向Web应用发送消息,并且未在Web文本区域中打印出来
    有人知道为什么Web应用程序不接收消息吗?
    在Android和iOS上测试。
    相关文件:https://facebook.github.io/react-native/docs/webview.html

编辑:遇到了一个可能会指出问题的行为。

当直接在Web浏览器中测试“从Web发送邮件”按钮时,文本区域会记录它已发送的邮件以及收到的自己的邮件。

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

当从React Native应用程序在WebView中尝试相同时,文本区域仅打印出来

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

WebView是否劫持了window.postMessage方法并注入了一个自定义方法?
文档中提到了这一点:
设置此属性将在您的webview中注入一个postMessage全局变量,但仍将调用postMessage的预先存在的值。
也许这是错误的,这就是问题所在?

xvw2m8pv

xvw2m8pv1#

我遇到了同样的问题,并通过将事件侦听器添加到文档而不是窗口来修复它。

window.addEventListener("message", ...

致:

document.addEventListener("message", ...
ibrsph3r

ibrsph3r2#

react-native-webview changes how this behavior works的版本5。您现在需要:

window.ReactNativeWebView.postMessage(data);
vu8f3i0k

vu8f3i0k3#

添加特定于浏览器的事件侦听器

安卓系统

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

iOS中

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

7jmck4yq

7jmck4yq4#

实际上,监听器在不同的操作系统(如iOS和Android)中的工作方式不同。因此,您应该使用document.addEventListener用于Android,window.addEventListener用于iOS。

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

eh57zj3b5#

以上答案都不适用于IOS,可能仍然适用于Android设备。这种方式适用于所有平台-
在react native中:

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));
      }

}

在JS侧-

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)
}
yruzcnhs

yruzcnhs6#

您可以按照下面的步骤进行Pub/Sub =〉〉

步骤1 =〉在react native app中添加插件:https://github.com/react-native-webview/react-native-webview
Step 2 =〉在ReactNative中添加以下代码(移动的部分):

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;

步骤3 =〉在ReactJS中添加以下代码(Web部件):

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;

现在您可以随时随地在移动的和网络之间收发信息了。

Output Image

ua4mk5z4

ua4mk5z47#

React原生代码

function getInjectableJSMessage(message) {
        return `
          (function() {
            document.dispatchEvent(new MessageEvent('message', {
              data: ${JSON.stringify(message)}
            }));
          })();
        `;
      }
function sendDataToWebView() {
    webviewRef.current?.injectJavaScript(
      getInjectableJSMessage("Hello")
    );
  }

React Web应用代码

React.useEffect(() => {
    function handleEvent(message) {
      console.log(message.data);
    }
    document.addEventListener("message", handleEvent);

    return () =>
      document.removeEventListener("message", handleEvent);
  }, []);

相关问题