17

I'm trying to use the onMessage listener. The website is executing a postMessage (window.postMessage("Post message from web");) but react native's webview onMessage listener is not doing anything! I don't know what I'm doing wrong.

Here is the HTML

<script type="text/javascript">
  window.postMessage("Post message from web");
</script>

And here is the react-native code:

  <WebView
    ref={( webView ) => this.webView = webView}
    onMessage={this.onMessage}
    source={{uri: 'https://app.sodge.co/login/response.html'}}
  />

onMessage react native function:

onMessage( event ) {
  Alert.alert(
    'On Message',
    event.nativeEvent.data,
    [
      {text: 'OK'},
    ],
    { cancelable: true }
  )
}

Here is an expo snack too... I don't know that I'm doing wrong (: ... https://snack.expo.io/S17AQqWbf

5 Answers 5

20

For anyone still confused about this... It is because communication between React Native and Webview has been completely rewritten. Yes, window.postMessage(data, *) has been changed to window.ReactNativeWebView.postMessage(data), but to answer this question specifically, the solution, i.e., what you need to support window.postMessage from your web view, is to pass the following prop per https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0:

const injectedJavascript = `(function() {
      window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`

<WebView
  injectedJavaScript={injectedJavascript}
  ref={( webView ) => this.webView = webView}
  onMessage={this.onMessage}
  source={{uri: 'https://app.sodge.co/login/response.html'}}
/>

Then you can call window.postMessage("Post message from web", "*") within your script tag (or whereever else) as usual.

UPDATE: The above answer only supports the old functionality of window.postMessage on Android - something not mentioned in the docs. For iOS, simply use the library, https://github.com/CharlesStover/react-native-web-view. Include the web view as you would normally - without the injected javascript. iOS does not support messages or injected javascript between native and webview. For more information, and to understand the hack to get around this, check out https://medium.com/@Charles_Stover/fixing-react-native-webviews-postmessage-for-ios-10e2320b2f14.

0
12

According to this issue, you need to wait until the React Native postMessage has replaced the native window.postMessage (don’t ask me why they are replacing a native function instead of creating a new one).

One solution is to do something like:

function waitForBridge() {

   //the react native postMessage has only 1 parameter
   //while the default one has 2, so check the signature
   //of the function

   if (window.postMessage.length !== 1){
     setTimeout(waitForBridge, 200);
   }
   else {
     window.postMessage('abc');
   }
}

window.onload = waitForBridge;
1
  • Unbelievable! I spent hours trying to figure out why i didn't receive any message back. May 2019 . React native expo sdk 32.0.0 And still this same stupid problem. Still perfectly valid question as to 'why' to '... replacing a native function'!
    – devplayer
    Commented May 20, 2019 at 15:12
12

If you use react-native-webview after v5.0.0 like me, use window.ReactNativeWebView.postMessage(data)!

window.postMessage(data, *) has been changed to

window.ReactNativeWebView.postMessage(data)

https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0

2
  • 3
    This is the real answer.
    – Siraj Alam
    Commented Jul 17, 2019 at 11:42
  • 1
    This should be a correct answer. Yes, the question is about receiving message but the REASON is because postMessage not working. Commented Jan 14, 2020 at 7:25
5

This solved my problem.

let postMessage = window.parent.postMessage;
if(window.ReactNativeWebView) {
    postMessage = window.ReactNativeWebView.postMessage;
}
postMessage('hey');

https://github.com/react-native-community/react-native-webview/issues/323#issuecomment-511824940

0
2

For me the solution was to override window.postMessage function using injectedJavaScriptBeforeContentLoaded prop instead of injectedJavaScript like below.

const injectedJavaScript = `
    window.postMessage = function(data) {
       window.ReactNativeWebView.postMessage(JSON.stringify(data));
    }
`

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.